Mastering Logistics Architecture: A Freight Brokerage System Class Diagram Guide

In the complex world of logistics and supply chain management, clarity is currency. A freight brokerage platform acts as the critical intermediary between shippers who need to move cargo and carriers who have the capacity to transport it. When building the software backbone for such a system, the architectural blueprint must be as robust as the trucks on the road. This is where diagramming-as-code shines, transforming abstract business rules into concrete, executable visual models that developers and stakeholders can instantly understand.

Real-world system context and operational workflow illustration

Using PlantUML within VPasCode allows you to define these complex relationships with precision. Instead of manually dragging boxes and lines, you write declarative code that describes the domain entities—such as Loads, Carriers, and Invoices—and their interactions. This approach ensures that your documentation remains synchronized with your codebase, reducing the friction between design and implementation. In this masterclass, we will construct a professional class diagram for a Freight Brokerage System, demonstrating how to model generalization, aggregation, and association relationships to capture the full lifecycle of a shipment.

Understanding the Model: Purpose, Scope & Problem Framing

Diagram Abstraction & Representation

A class diagram in the context of a logistics platform serves as the structural backbone of the application. It maps the domain model, defining the static structure of the system by specifying classes, their attributes, and operations. In this specific Freight Brokerage scenario, the diagram represents the core business entities that drive revenue and operational flow. It visualizes how a Broker facilitates transactions between a Shipper and a Carrier, while managing the Load object that represents the physical cargo.

Target Domain Scope & Scenario

This model covers the central domain of a brokerage platform. It intentionally excludes peripheral systems like payment gateways or external GPS tracking APIs, focusing instead on the internal data structures required to manage a shipment from request to delivery. The scope includes load specification, rate agreements, contract management, and the tracking of shipment status events. By isolating these core components, we create a clear boundary for the system’s primary responsibility: matching supply with demand efficiently.

Key Takeaways & Educational Insights

By following this tutorial, you will learn how to model real-world logistics constraints using PlantUML syntax. You will gain insights into representing one-to-many relationships (e.g., a broker managing many loads), handling inheritance hierarchies (e.g., Users extending to specific roles), and using enumerations to restrict state values like LoadStatus or TransitStatus. This clarity is essential for maintaining a scalable architecture in high-volume transportation environments.

Complete Diagram & Full Source Code

Below is the finished blueprint of the Freight Brokerage System. This diagram encapsulates the core domain logic, visualizing the interactions between brokers, carriers, shippers, and the loads they manage.

Descriptive Alt Text

@startuml
!include https://static.visual-paradigm.com/web/resources/plantuml-stdlib/themes/rose.puml

title Freight Brokerage System Class Diagram

/'
This class diagram models the core domain of a freight brokerage platform.
The system connects shippers who need to move cargo with carriers who have available trucks.
Key functional areas include load management, carrier procurement, contract pricing,
shipment tracking, document handling, and customer relationship management.

The diagram captures the following main responsibilities:
- Load lifecycle (creation, posting, assignment, delivery)
- Carrier qualification and performance tracking
- Rate negotiation and contract management
- Shipment visibility and event logging
- Invoicing and payment settlement
- User roles (broker, shipper, carrier, dispatcher)
'/

class Broker {
  - brokerId: UUID
  - name: String
  - licenseNumber: String
  - mcNumber: String
  - commissionRate: Double
  + onboardCarrier(carrier: Carrier)
  + postLoad(load: Load)
  + assignLoad(load: Load, carrier: Carrier)
  + generateInvoice(load: Load)
}

class Shipper {
  - shipperId: UUID
  - companyName: String
  - creditRating: String
  - billingAddress: Address
  + requestQuote(loadSpec: LoadSpecification)
  + approveLoad(load: Load)
  + payInvoice(invoice: Invoice)
}

class Carrier {
  - carrierId: UUID
  - dotNumber: String
  - scacCode: String
  - fleetSize: Integer
  - insuranceExpiry: Date
  + acceptLoad(load: Load)
  + submitStatusUpdate(load: Load, status: ShipmentStatus)
  + viewAvailableLoads()
}

class Load {
  - loadId: UUID
  - origin: Address
  - destination: Address
  - pickupWindow: TimeWindow
  - deliveryWindow: TimeWindow
  - weight: Double
  - volume: Double
  - equipmentType: EquipmentType
  - status: LoadStatus
  - postedDate: DateTime
  + updateStatus(newStatus: LoadStatus)
  + calculateRate(): Money
  + isEligibleForCarrier(carrier: Carrier): Boolean
}

class LoadSpecification {
  - commodity: String
  - weight: Double
  - volume: Double
  - specialHandling: List<String>
  - requiredEquipment: EquipmentType
  + validate(): Boolean
}

class RateAgreement {
  - agreementId: UUID
  - effectiveDate: Date
  - expiryDate: Date
  - ratePerMile: Money
  - fuelSurchargeFormula: String
  - minimumCharge: Money
  + calculateTotalCost(distance: Double): Money
  + isActive(): Boolean
}

class Contract {
  - contractId: UUID
  - startDate: Date
  - endDate: Date
  - terms: String
  - volumeCommitment: Double
  - penaltyClause: String
  + renew()
  + terminate()
}

class Shipment {
  - shipmentId: UUID
  - actualPickup: DateTime
  - actualDelivery: DateTime
  - transitStatus: TransitStatus
  - currentLocation: GeoPoint
  + updateLocation(lat: Double, lon: Double)
  + recordDelay(reason: String)
  + isOnTime(): Boolean
}

class TrackingEvent {
  - eventId: UUID
  - timestamp: DateTime
  - eventType: EventType
  - description: String
  - location: GeoPoint
  - isException: Boolean
}

class Invoice {
  - invoiceId: UUID
  - invoiceNumber: String
  - issueDate: Date
  - dueDate: Date
  - baseAmount: Money
  - fuelSurcharge: Money
  - accessorialCharges: Money
  - totalAmount: Money
  - status: InvoiceStatus
  + applyPayment(amount: Money)
  + markOverdue()
}

class Payment {
  - paymentId: UUID
  - amount: Money
  - paymentDate: DateTime
  - method: PaymentMethod
  - referenceNumber: String
  + process()
  + reverse()
}

class User {
  - userId: UUID
  - email: String
  - passwordHash: String
  - role: UserRole
  - lastLogin: DateTime
  + authenticate(password: String): Boolean
  + resetPassword()
}

class Address {
  - street: String
  - city: String
  - state: String
  - zipCode: String
  - country: String
  + fullAddress(): String
  + geocode(): GeoPoint
}

enum LoadStatus {
  DRAFT
  OPEN
  ASSIGNED
  IN_TRANSIT
  DELIVERED
  CANCELLED
}

enum TransitStatus {
  PENDING
  EN_ROUTE
  ARRIVED
  DELAYED
  COMPLETED
}

enum EquipmentType {
  DRY_VAN
  REEFER
  FLATBED
  STEP_DECK
  HOT_SHOT
}

enum InvoiceStatus {
  DRAFT
  SENT
  PARTIALLY_PAID
  PAID
  OVERDUE
  WRITTEN_OFF
}

Broker "1" -- "0..*" Load : posts
Shipper "1" -- "0..*" Load : requests
Carrier "0..*" -- "0..*" Load : bids on
Carrier "1" -- "0..*" RateAgreement : has
Shipper "1" -- "0..*" RateAgreement : negotiates
Broker "1" -- "0..*" Contract : manages
Shipper "1" -- "0..*" Contract : signs
Carrier "1" -- "0..*" Contract : signs
Load "1" -- "1" Shipment : generates
Shipment "1" -- "0..*" TrackingEvent : logs
Load "1" -- "0..1" Invoice : billed for
Invoice "1" -- "0..*" Payment : receives
Broker "1" -- "0..*" Carrier : works with
Broker "1" -- "0..*" Shipper : serves
Load "1" -- "1..*" Address : involves
User --|> Broker : extends
User --|> Shipper : extends
User --|> Carrier : extends
LoadSpecification "1" -- "1" Load : defines
RateAgreement "0..*" -- "1" Load : applies to
@enduml

Step-by-Step Architectural Walkthrough

Constructing a complex domain model requires a phased approach. We will break down the construction of this Freight Brokerage diagram into logical stages, starting from the canvas setup to the final relationship mapping.

Phase 1: Canvas Configuration & Layout Directives

Every PlantUML diagram begins with directives that define its scope and visual style. We start with @startuml to open the diagram and import a theme to ensure professional styling without manual CSS work. The title directive provides a clear header for documentation, while the comment block (/' ... '/) serves as living documentation for future maintainers.

@startuml
!include https://static.visual-paradigm.com/web/resources/plantuml-stdlib/themes/rose.puml

title Freight Brokerage System Class Diagram
/'
This class diagram models the core domain of a freight brokerage platform.
... (comment block continues)
'/

Phase 2: Declaring Core Entities, Actors, and Boundaries

The foundation of the system lies in the core classes. We define Broker, Shipper, and Carrier as the primary actors. Each class is defined with attributes (prefixed with - for private) and methods (prefixed with + for public). For example, the Broker class manages the commission rates and handles the onboarding of carriers.

class Broker {
  - brokerId: UUID
  - name: String
  + onboardCarrier(carrier: Carrier)
  + postLoad(load: Load)
}

class Carrier {
  - carrierId: UUID
  - dotNumber: String
  + acceptLoad(load: Load)
}

Phase 3: Mapping Data Flows & Key Interactions

Relationships define how these entities interact. In logistics, a broker posts a load, but a carrier bids on it. We use association lines (--) with cardinality labels to express these constraints. For instance, one Broker can post many Loads, but a Load is posted by exactly one Broker.

Broker "1" -- "0..*" Load : posts
Carrier "0..*" -- "0..*" Load : bids on

Phase 4: Grouping, Annotations & Visual Polish

Finally, we incorporate inheritance and enumerations to refine the model. The User class acts as a parent for Broker, Shipper, and Carrier, using the generalization arrow (--|>). Enumerations like LoadStatus ensure data integrity by restricting values to valid states like DRAFT or IN_TRANSIT.

User --|> Broker : extends
User --|> Shipper : extends

enum LoadStatus {
  DRAFT
  OPEN
  ASSIGNED
  IN_TRANSIT
  DELIVERED
  CANCELLED
}

Syntax & Keyword Deep Dive

To master PlantUML class diagrams, you must understand the specific syntax keywords that drive the rendering engine. Here is a breakdown of the critical elements used in this Freight Brokerage model:

  • class: Declares a class definition. It can include attributes and methods separated by newlines. Attributes use - for private and + for public visibility.
  • --: Represents an association relationship between two classes. You can add cardinality labels (e.g., "1" -- "0..*") to specify multiplicity constraints.
  • --|>: Represents generalization (inheritance). This indicates that a child class (like Broker) extends a parent class (like User).
  • enum: Defines an enumeration type, listing specific allowed values for a property, such as LoadStatus or EquipmentType.
  • title: Sets the main heading of the diagram, useful for documentation and embedding.
  • /' ... '/: Creates a multi-line comment block that appears in the rendered diagram as a note, providing context without affecting the logic.

Best Practices & Pitfalls to Avoid

When modeling complex logistics systems, maintaining readability is paramount. Follow these guidelines to ensure your PlantUML diagrams remain effective over time.

  • Use Clear Cardinalities: Always specify the multiplicity (e.g., "1", "0..*") on associations. Ambiguity in relationships leads to database design errors later.
  • Separate Value Objects: Entities like Address or Money should be distinct classes to promote reuse and consistency across the model.
  • Limit Class Depth: Avoid nesting too many attributes or methods in a single class. If a class becomes too large, consider splitting it into smaller, cohesive components.
  • Document Intent: Use the comment block (/' ... '/) to explain the business rules behind the model, not just the code syntax.

Try It Yourself with VPasCode

Start Building Logistics Architecture Diagrams Faster with VPasCode

Instantly prototype and refine your Freight Brokerage System class diagrams online with VPasCode’s free, browser-based PlantUML editor.

Scroll to Top