Event-Driven Architecture: Events, Queues, and Reliable Consumers
Understand event-driven architecture, queues, pub-sub, consumer retries, ordering, idempotency, outbox publishing, and operational trade-offs.
On this page
Event-driven architecture lets one component publish that something happened while other components react independently. It can reduce coupling and improve resilience, but it introduces delivery, ordering, duplication, and observability concerns.
#Events, commands, and queues
An event describes a fact such as InvoicePaid. A command asks a specific component to perform work. A queue usually delivers work to one consumer group; pub-sub lets multiple subscribers receive a copy.
#Design event contracts
Include a stable ID, type, version, time, source, tenant, and payload. Document whether consumers can replay events and whether the payload is a snapshot or a reference. Add fields rather than changing meanings silently.
#Delivery and idempotency
Assume at-least-once delivery unless the platform guarantees otherwise. Consumers should persist event IDs or use a domain version so duplicates do not repeat side effects. Downstream operations need their own idempotency keys when they are externally visible.
#Retries and dead letters
Retry temporary failures with backoff. Do not retry permanent validation errors indefinitely. Put exhausted messages in a dead-letter flow with enough context for a safe replay.
#Outbox publishing
The outbox pattern records a domain change and outgoing event in one database transaction. A publisher then delivers the event. This avoids losing a message when the database commit succeeds but the process crashes before publishing.
#Ordering and operations
Events may be delayed or reordered. Use sequence or domain versions when order matters and make the consumer reject older updates. Monitor queue age, retry counts, consumer lag, dead letters, processing duration, and failures.
#Frequently asked questions
#Are events always asynchronous?
They are commonly asynchronous, but the important property is that the publisher does not need to know every consumer’s implementation.
#Do queues guarantee exactly once?
Do not assume it. Design consumers to tolerate duplicates and retry.
#Conclusion
Event-driven systems are reliable when contracts, retries, idempotency, ordering, and operations are explicit. Start with one workflow and a replayable event before introducing a large messaging topology.