Async & messaging: multiple-choice review
Multiple-choice synthesis across the async unit: delivery semantics and effectively-once, queue vs log and replay, choreography vs orchestration, the outbox against dual writes, and the unbounded-queue backlog trap.
Six questions that cut across the whole unit. Each is a decision you make when you put a queue in a design, choose a coordination style, or review an async pipeline — not a definition to recite, but the judgement calls behind delivery semantics, the outbox, and the backlog trap.
Confirm you can pick a delivery semantic and make it effectively-once, choose queue vs log from a replay requirement, place a process on the choreography/orchestration axis, recognize and fix a dual write with the outbox, and reject an unbounded queue from its backlog behaviour.
A vendor advertises 'exactly-once delivery' for its queue. What's the accurate way to read that, and what must your consumer still do?
You must onboard a new consumer that reprocesses the last 14 days of events to build a fresh view. Which messaging substrate supports this directly?
A 7-step order process needs compensating actions on failure (refund, release stock), and on-call must answer 'where is order #X right now?'. Which coordination style fits?
A handler does `db.commit(order)` then `broker.publish(event)`; occasionally the order is saved but the event never fires. What's the bug and the standard fix?
A pipeline uses an unbounded queue 'so we never drop events.' A downstream stalls for 30 minutes at peak. What's the most likely result, and the root fix?
On a Kafka topic with 6 partitions, you need each account's events processed in order while parallelizing across accounts. How do you key and consume?
- 01Why is 'exactly-once delivery' really effectively-once, and what does that demand of you?
- 02How does the outbox defeat the dual-write problem, and what guarantee does it give?
The through-line of this unit is that asynchrony buys decoupling and pays in semantics you must design around. A queue turns a synchronous availability dependency into an asynchronous latency one, but delivery is honestly at-least-once (or lossy at-most-once), so exactly-once is effectively-once — idempotent consumers with a dedup key. Pub/sub fans out across subscribers, and the deep split is broker vs log: a log retains messages and tracks per-consumer offsets, making replay and backfill first-class while a delete-on-consume broker can’t. Coordinating multi-step processes is choreography (decoupled, simple flows) vs orchestration (a saga that holds process state and compensations — for complex flows). The transactional outbox defeats the dual-write problem by making the state change and the event one local transaction with an async relay, guaranteeing “never lost, possibly duplicated.” And every queue needs a bound: an unbounded queue is a latent disaster that launders a brief stall into a long backlog, so you bound, shed load, rate-limit per tenant, and alarm on lag. At this depth, the senior move is to name the tradeoff before adding the component.
Something unclear?
Ask a question about this lesson. Questions are anonymous and go straight to the author to make the lesson better.