Explainstuff.mebeta
All concepts
Cloud Native Patternsadvanced7 min

Sequential Convoy

Process related messages strictly in order while still scaling out across many consumers for everything unrelated.

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.

Before — competing consumers reorder related messages
related messages processed out of order
One queue · order A: Created, Cancelled
Worker 1 · Cancelled
Worker 2 · Created
Order A: live again?!
Plain competing consumers scale beautifully but destroy ordering: Created and Cancelled for the same order land on different workers and race, so a cancelled order can spring back to life.

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.

Sequential Convoy — many lanes, ordered within each
ordered within each group
Mixed messages
Group by key
Consumer · order A
Consumer · order B
Consumer · order C
Mixed messages are split by group key into per-order convoys; each consumer processes one group strictly in order while unrelated groups run fully in parallel.
Tip

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.

Key takeaways

  • Some messages must be handled in the exact order they were sent — but only relative to others in the same group.
  • A sequential convoy groups messages by a key (like a customer or order id) and guarantees ordering within each group.
  • Different groups are fully independent, so they run in parallel — you keep throughput while preserving per-group order.
  • Messaging features like sessions or partitions implement the convoy by pinning one group's messages to one consumer at a time.
  • It's the ordered counterpart to competing consumers: scale freely across groups, stay strictly ordered within each one.

Keep going