Overview
Message ordering is whether consumers process messages in the order they were produced. Global ordering across all messages is expensive, since it forces everything through one sequence and one consumer. Most systems instead guarantee ordering per key: all messages for one order, user, or account are processed in sequence, while different keys are processed in parallel.
Ordering can break in many ways: multiple producers, retries that reorder sends, parallel consumers, rebalances, and messages moved to DLQs. Designs either preserve order per key (partitioning, FIFO groups, single-threaded processing per key) or make consumers tolerant of out-of-order delivery using sequence numbers and versions.
Chapters of one book must be read in order, but you and a friend can read different books at the same time. Ordering per book (key) is enough; nobody needs a global order across all books.
When to use it
- State changes that must be applied in sequence (created, paid, shipped).
- Financial transactions per account.
- Chat messages within a conversation.
- Replicating database changes (CDC).
Where it shows up in interviews
Recognize it when: events for an order must apply in sequence.
- Design order state tracking
- Design a bank transaction processor
Recognize it when: events may arrive late or reordered.
- Design a chat system with message sequencing
- Design CDC into a search index
Where it is used in real software
With idempotent producers, Kafka preserves order per partition even with retries.
Order is strict within a MessageGroupId; different groups process in parallel.
Slack and Discord assign per-channel sequence IDs so clients sort and detect gaps.
Key terms
- Total order
- One global sequence for all messages.
- Per-key (partial) order
- Sequence guaranteed within a key.
- Sequence number
- Monotonic number per key to detect reordering and gaps.
- Head-of-line blocking
- One stuck message blocks all later messages for its key.
How it works, step by step
- 1Decide the ordering scope
Usually per entity, not global.
- 2Route by key
Same key to the same partition or FIFO group.
- 3Produce safely
Idempotent producers, or one in-flight request per partition.
- 4Consume sequentially per key
One thread per partition, or per-key queues.
- 5Defend with versions
Ignore events older than the stored version.
How ordering breaks and fixes
Events for order-9: Placed (1), Paid (2), Shipped (3)
| Cause | What happens | Fix |
|---|---|---|
| Different partitions | Shipped processed before Paid | Key by orderId |
| Producer retry without idempotence | Paid written after Shipped | Idempotent producer |
| Parallel threads in a consumer | Handlers race | Serialize per key |
| Late duplicate of Placed | Status reset to placed | Version check: ignore seq <= stored |
NOWCause: Different partitions | What happens: Shipped processed before Paid | Fix: Key by orderId
Combine partition-by-key for normal ordering with version checks as a safety net.
Implementation
-- Apply an event only if it is newer than what we have (out-of-order tolerant)UPDATE orders_viewSET status = $2, last_seq = $3, updated_at = now()WHERE order_id = $1 AND last_seq < $3;-- 0 rows updated: stale or duplicate event, safely ignoredComplexity and performance
Does not scale.
Common choice.
Trade-offs
Stronger ordering reduces parallelism; per-key ordering balances both.
Blocking a key until a failed message succeeds preserves order but stalls that key.
Variants and related techniques
Consumers buffer out-of-order messages until gaps fill.
Design updates so order does not matter (CRDTs, increments).
Common mistakes
- Assuming a queue preserves order.
Fix: Standard SQS and most multi-consumer queues do not; check guarantees.
- Relying on timestamps for order.
Fix: Clocks skew; use per-key sequence numbers.
Interview questions
How do you guarantee ordering in a distributed message system?
Guarantee it per key: partition by the entity ID, use idempotent producers, process each partition sequentially, and protect consumers with sequence or version checks for late or duplicate events.
How do chat apps order messages?
The server assigns a per-conversation sequence number when it accepts a message; clients display by sequence and fetch missing ranges if they detect gaps.
Practice problems
| Problem | Difficulty | What it trains |
|---|---|---|
| Make an order-status projector out-of-order safe | Medium | Version checks. |
| Design message ordering for group chat | Hard | Sequencing and gaps. |