A single relay process that had become the throughput ceiling, split into two by partitioning on the aggregate identifier.
-- each relay claims its own partition
SELECT * FROM outbox
WHERE published_at IS NULL
AND CRC32(HEX(aggregate_id)) % 2 = ?
ORDER BY id
LIMIT 200;
-- ordering within an aggregate is preserved because
-- one aggregate is always handled by one relay.
The modulo on a hash of the aggregate id is what preserves per-aggregate ordering while allowing parallelism, and it is the same idea as a partition key on the broker side. Changing the number of relays reshuffles the assignment, so a rollout has to drain first — which is a constraint worth knowing before it is discovered during a scale-up.