Skip to content
Kumar Chandrachooda
Series

The Order That Choreographs Itself

In reading order.

  • 15 parts
  • ≈ 96 min total
  • 15 published
Part 1 01 Nov 2025 6 min read

The Order That Choreographs Itself

Nobody in Pacco approves an order - a vehicle reservation does. A tour of DevMentors' parcel-delivery estate, the domain it models, and the fifteen-part series it earns.

Part 2 04 Nov 2025 6 min read

Three Ages of a Domain Model

Same framework, same four-project layout, three maturities - Parcels publishes from handlers, Orders raises events and maps them inline, Availability runs a full pipeline. The lineage made diffable.

Part 3 07 Nov 2025 6 min read

The Reservation That Bumps You

Availability's Resource aggregate enforces one real business rule - a higher-priority reservation evicts yours and announces it. The invariant, the struct value object behind it, and the day-integer it becomes on disk.

Part 4 09 Nov 2025 6 min read

One Event, Five Contracts

Every transition of Pacco's Order raises the same domain event - OrderStateChanged - and a mapper switches on aggregate status to mint five distinct integration events. A content-based router keyed on state, weighed honestly.

Part 5 12 Nov 2025 6 min read

A Checkout With No Conductor

Pacco's flagship flow reconstructed from source - a vehicle is assigned, a reservation lands, an order approves itself, and when a VIP bumps the booking the cancellation ripples through three services with no process manager in sight.

Part 6 15 Nov 2025 6 min read

Correlation by Natural Key

Availability's ResourceReserved event carries no order id, no correlation id, no saga id - just a resource and a date. Orders finds the right order anyway, by treating (vehicleId, deliveryDate) as the correlation key, and the expropriation flow shows exactly when that key stops being unique.

Part 7 18 Nov 2025 7 min read

Rejected Events and How They Rot

Convey's IRejectedEvent gives Pacco an application-level negative acknowledgement - a rejected twin for every command. Reading the four exception-to-message mappers shows the pattern decaying in four different ways, from a failed reserve announced as a failed release to rejection classes nothing ever constructs.

Part 8 21 Nov 2025 6 min read

The Parcel That Wouldn't Leave

Order.DeleteParcel raises a ParcelDeleted event and never removes the parcel from the set, while Parcels' cancel and delete handlers detach exactly one parcel of many. Two bounded contexts maintain the same association independently, both with bugs, and end up permanently disagreeing about a fact.

Part 9 24 Nov 2025 6 min read

Same Fact, Two Names

Inside the Customers service a registration completes - and the rest of the estate hears that a customer was created. Three lines of EventMapper perform the best ubiquitous-language translation in Pacco, sitting on top of a lifecycle state machine with one guarded transition and four administrative jumps.

Part 10 27 Nov 2025 7 min read

Three Ways to Borrow Another Service's Data

Four Pacco services need customer data and no two agree on how to get it - Orders and Parcels keep id-only replicas fed by events, Availability phones home mid-command, and Pricing pulls the full details document to count one number. One upstream, three consistency stances, five representations of the same entity.

Part 11 29 Nov 2025 7 min read

The Outbox With Transactions Turned Off

Every Pacco service that enables Convey's Mongo outbox also sets disableTransactions to true - the aggregate write and the outbox write are separate operations, the pattern's one guarantee switched off in configuration. Meanwhile the inbox that would absorb the resulting duplicates sits beside three handlers that throw on them.

Part 12 02 Dec 2025 6 min read

CQRS at the Transport Layer

In Pacco the CQRS split is not a diagram - it is wiring you can read. Every command arrives through two front doors, RabbitMQ subscription and controller-less HTTP dispatch, while queries ride HTTP only; commands assign their own ids in the constructor, and a marker attribute turns each service into its own runtime contract registry.

Part 13 05 Dec 2025 6 min read

Optimistic Concurrency That Never Says No

Availability guards every save with a version-filtered ReplaceOneAsync - and discards the result, so a lost update is indistinguishable from a successful one and the integration event ships either way. Three folders away, Orders and Customers inherit the same AggregateRoot name with the versioning quietly deleted.

Part 14 08 Dec 2025 7 min read

One Request, Four Services

AssignVehicleToOrder is the one command in Pacco that cannot finish alone - Orders calls Vehicles, then Pricing, and Pricing calls Customers, a synchronous enrichment chain on the write path of a messaging estate. At the end of it sits a deliberately bus-less calculator with a loyalty ladder, an unassigned Id and a discount logged in dollars.

Part 15 11 Dec 2025 8 min read

Rich Rules, Demo-Grade Data

The series retrospective - Pacco's domain teaches real rules (state machines, priority expropriation, loyalty ladders, compensations) on top of cardboard data (bare-decimal prices, one vehicle per order, size-cube parcels, no payment, and a capacity check that ships in two halves nobody ever connects). What to steal, what to distrust, and what fourteen parts of source-reading add up to.