MESSAGING & EVENT-DRIVEN ARCHITECTURE / SYSTEM CONCEPT BRIEF

Message ordering

Message ordering is whether consumers process messages in the order they were produced.

IntermediatePhase 06 / Topic 16 of 18RequirementsTrade-offsFailure modes
01

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 a book

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.

02

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).
03

Where it shows up in interviews

Per-entity ordering

Recognize it when: events for an order must apply in sequence.

  • Design order state tracking
  • Design a bank transaction processor
Out-of-order tolerance

Recognize it when: events may arrive late or reordered.

  • Design a chat system with message sequencing
  • Design CDC into a search index
04

Where it is used in real software

Kafka per-partition order

With idempotent producers, Kafka preserves order per partition even with retries.

SQS FIFO message groups

Order is strict within a MessageGroupId; different groups process in parallel.

Chat apps

Slack and Discord assign per-channel sequence IDs so clients sort and detect gaps.

05

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.
06

How it works, step by step

  1. 1
    Decide the ordering scope

    Usually per entity, not global.

  2. 2
    Route by key

    Same key to the same partition or FIFO group.

  3. 3
    Produce safely

    Idempotent producers, or one in-flight request per partition.

  4. 4
    Consume sequentially per key

    One thread per partition, or per-key queues.

  5. 5
    Defend with versions

    Ignore events older than the stored version.

07

How ordering breaks and fixes

Events for order-9: Placed (1), Paid (2), Shipped (3)

Step 1 / 4
CauseWhat happensFix
Different partitionsShipped processed before PaidKey by orderId
Producer retry without idempotencePaid written after ShippedIdempotent producer
Parallel threads in a consumerHandlers raceSerialize per key
Late duplicate of PlacedStatus reset to placedVersion 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.

08

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 ignored
09

Complexity and performance

Global order throughputOne sequence

Does not scale.

Per-key order throughputScales with keys and partitions

Common choice.

10

Trade-offs

Ordering vs parallelism

Stronger ordering reduces parallelism; per-key ordering balances both.

Ordering vs availability

Blocking a key until a failed message succeeds preserves order but stalls that key.

11

Variants and related techniques

Sequence numbers with buffering

Consumers buffer out-of-order messages until gaps fill.

Commutative operations

Design updates so order does not matter (CRDTs, increments).

12

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.

13

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.

14

Practice problems

ProblemDifficultyWhat it trains
Make an order-status projector out-of-order safeMediumVersion checks.
Design message ordering for group chatHardSequencing and gaps.