I look for ordering bugs when data seems to appear in the wrong state. A shipment before an order or a refund before a charge is usually not missing data; it is an ordering rule that the system failed to enforce.
Order needs a scope
I am looking at the messy part here: late messages, duplicates, missing messages, and the decision the system makes.
Global order is expensive and often unnecessary. Most systems need order within a customer, account, order, or partition. Naming that scope keeps the design both correct and practical.
Event log example
The real workflow matters here. It shows the ownership gaps that a clean definition usually hides.
An order service emits OrderCreated, PaymentCaptured, and OrderShipped. The warehouse consumer must apply them in that order for each order id.
Ordered consumer code
A useful snippet tells me what the system will do when the input is not perfect.
Consumers should apply events only when the next sequence is present:
void apply(OrderEvent event) {
long expected = lastSequence.get(event.orderId()) + 1;
if (event.sequence() != expected) return;
state.apply(event);
lastSequence.put(event.orderId(), event.sequence());
}
The handler applies only the next expected sequence number. Out-of-order events wait instead of corrupting state with a future update.
Sequence diagram: preserve order per order id
The system does not need one order for the whole company. It needs a correct order for this order id.
The ordering contract
- Define the ordering scope before choosing the tool.
- Partition streams by the key that needs ordered handling.
- Make consumers reject impossible transitions.