Inside Dispatch
c4
C4 level 3: the components of the service that owns parcel state
/
Fit
SVG
PNG
Dispatch
CONTAINER BOUNDARY
Delegates out-of-area parcels to
Requests a retry stop from
Proposes a transition to
Delivers scans to [Kafka]
Asks what happens next
Writes stops through
Sequences with [gRPC]
Reads / writes [SQL]
Persists through
Publishes [Kafka]
Emits through
Scan consumer — [Kafka listener] — Reads parcel.scanned and orders events by when they happened, not when they arrived
Scan consumer
[Component: Kafka listener]
Reads parcel.scanned and orders
events by when they happened, not
when they arrived
State machine — [Java] — The only thing that changes a parcel's status, and refuses any move the table does not permit
State machine
[Component: Java]
The only thing that changes a
parcel's status, and refuses any
move the table does not permit
Attempt policy — [Java] — Decides whether a failed delivery is retried tomorrow or parked for the recipient
Attempt policy
[Component: Java]
Decides whether a failed delivery
is retried tomorrow or parked for
the recipient
Route planner — [Java] — Places a parcel on a route and asks the routing engine to sequence it
Route planner
[Component: Java]
Places a parcel on a route and
asks the routing engine to
sequence it
Partner hand-off — [Java] — Sends out-of-area parcels to a partner carrier and stops tracking them
Partner hand-off
[Component: Java]
Sends out-of-area parcels to a
partner carrier and stops tracking
them
Event publisher — [Kafka producer] — Emits parcel.delivered, parcel.attempt-failed and parcel.exception after the state change commits
Event publisher
[Component: Kafka producer]
Emits parcel.delivered,
parcel.attempt-failed and
parcel.exception after the state
change commits
Parcel repository — [JDBC] — The only component here that touches the database
Parcel repository
[Component: JDBC]
The only component here that
touches the database
Parcel events — [Kafka] — Where scans arrive from, and where state changes go
Parcel events
[Queue: Kafka, external]
Where scans arrive from, and where
state changes go
Relay DB — [PostgreSQL 15] — The parcel, route and scan tables
Relay DB
[Database: PostgreSQL 15, external]
The parcel, route and scan tables
Routing engine — [Python] — Sequences a van’s stops under time windows
Routing engine
[Container: Python, external]
Sequences a van’s stops under time
windows
Delegates out-of-area parcels to
Delegates out-of-area parcels to
Requests a retry stop from
Requests a retry stop from
Proposes a transition to
Proposes a transition to
Delivers scans to [Kafka]
Delivers scans to
[Kafka]
Asks what happens next
Asks what happens next
Writes stops through
Writes stops through
Sequences with [gRPC]
Sequences with
[gRPC]
Reads / writes [SQL]
Reads / writes
[SQL]
Persists through
Persists through
Publishes [Kafka]
Publishes
[Kafka]
Emits through
Emits through
drag to pan · wheel to zoom · click a node · Esc clears
Why this is one service
Parcel state, attempt policy and route placement change together; splitting them would need a distributed transaction to stay correct.
Everything grey lives outside Dispatch and is drawn only to show where the edges go.