NOTE
1.2 Message Ordering
How to preserve per-entity message order through partitioning, producer sequencing, consumer concurrency control, and idempotent version checks.
This is a historical learning note and may contain outdated or incomplete understanding.
1. The Problem
Suppose an entity produces:
1. create order
2. update order
If the messages are processed concurrently by unrelated consumers, the update can reach the database before the create.
The broker may have preserved publication order while the consumer execution reordered side effects.
2. Define the Ordering Scope
Do not request global ordering unless the business truly requires it.
Usually the real requirement is:
events for the same order/user/account must be processed in order.
Different entities can still run concurrently.
3. Partition by Entity Key
Choose a stable routing key such as order_id so all events for that entity map to the same broker partition/queue.
Kafka preserves record order within a partition. Consumer-group assignment then gives one consumer ownership of that partition at a time.
4. Preserve Order Inside the Consumer
Even when records arrive in order, a consumer can break ordering by handing them to a generic parallel thread pool.
Options include:
- process the partition sequentially;
- use a per-key serial executor;
- shard worker queues by the same key;
- attach entity versions and reject stale updates.
5. Retries Can Reorder
If message 1 fails but message 2 succeeds, retrying message 1 later can violate logical order.
For strict per-key ordering, pause later messages for that key/partition or route failures through an ordered retry mechanism.
6. Versioning as a Safety Net
Include monotonic versions/sequence numbers and let the target state machine reject stale transitions. This protects correctness even when transport or retry behavior is imperfect.