Think of a supermarket with ten checkout lanes. The lanes run in parallel — that's how the store serves a crowd quickly. But within any one lane, customers are still served strictly in the order they queued; you can't have someone's groceries scanned before the person ahead of them. Many lanes, but order preserved inside each.
The Sequential Convoy pattern brings exactly this to message processing. You want the throughput of many parallel consumers, but certain messages — all the events for a single order, say — must be processed in the order they arrived. The convoy lets you have both: parallelism across groups, strict sequence within each group.
The problem
The usual way to scale message processing is competing consumers: throw many workers at one queue and let them grab messages as fast as they can. It's wonderfully scalable — and it completely destroys ordering. Two messages for the same order, Created then Cancelled, might be picked up by different workers and processed out of sequence, leaving you with a cancelled order that then springs back to life.
The naive fix is to serialize everything through a single consumer so order is guaranteed. But now you've thrown away all your scalability for the sake of a constraint that only ever mattered within a group. The vast majority of messages have nothing to do with each other; forcing them through one lane to protect the few that are related is a terrible bargain.
- One shared queueHolds two events for the same order — Created then Cancelled — that must be applied in that order to be correct.
- Competing consumersMany workers grab messages as fast as they can. Two events for the same order land on different workers and race each other.
- Corrupted stateCancelled is applied before Created, so the cancellation is lost and the order springs back to life — silent data corruption.
How it works
The key insight is that ordering only matters relative to related messages. So you give each message a group key — a customer id, an order id, an account number. The messaging system then guarantees that all messages sharing a key form a convoy: they're delivered to, and processed by, a single consumer one at a time, in order.
Messages with different keys belong to different convoys and are free to run on different consumers simultaneously. Most platforms implement this with sessions or partitions — a feature that pins a group's messages to one consumer until it's done with them, then frees that consumer for another group. You get per-group ordering for free and full parallelism across groups. The diagram below shows mixed messages arriving, being split into ordered per-key convoys, and fanning out to consumers that each own one group at a time.
- Group by keySessions or partitions split the stream by a group key (an order id, a customer id) so each group's messages stay together and in order.
- ConsumerOwns one group at a time and processes its messages strictly in sequence. Different groups run on different consumers in parallel.
Choose the group key carefully — it sets both your ordering guarantee and your ceiling on parallelism. Too coarse a key (e.g. one per region) forces unrelated work to share a lane and throttles throughput. Too fine a key risks splitting messages that actually need ordering into separate convoys. The key is the design.
When to use it
Use a sequential convoy when ordering matters within a group but not globally — order lifecycle events, per-account transactions, per-device telemetry where state transitions must apply in sequence. It builds directly on queue-load-leveling for absorbing bursts and on pub-sub or partitioned topics that expose the session/partition feature the convoy relies on. Think of it as competing consumers with a per-key ordering guarantee layered on top.
It isn't free. You depend on a messaging system that supports sessions or partitions, and a single hot group can become a bottleneck since its messages can't be parallelized. If ordering genuinely doesn't matter, plain competing consumers is simpler and faster. But when out-of-order processing would corrupt your data, the convoy is how you keep correctness without giving up the ability to scale.