Core Cloud Architecture · Part 8 of 13
Messaging and Event-Driven Architecture
Moving work out of the request path, and the guarantees you take on when you do.
Plenty of work doesn't need to happen while the caller waits: sending an email, generating a report, resizing an uploaded image. Forcing it into the request/response cycle makes the caller sit through work whose result it doesn't need yet. Messaging systems exist to move that work out of the request path.
Queues
A queue holds messages until a consumer is ready to process them, typically one consumer per message (once processed, the message is removed or marked complete). It's the basic building block of asynchronous processing: a web request drops a message on the queue and returns immediately, while a separate worker process picks the message up and does the work on its own schedule, potentially much slower than the original request would tolerate.
Pub/sub
Publish/subscribe (pub/sub) broadcasts a message to every subscriber interested in it, rather than to exactly one consumer. A single event, "order placed," might need to trigger inventory update, a confirmation email, and an analytics record, each handled by a different, independent subscriber, without the publisher needing to know any of them exist.
Event buses
An event bus is pub/sub with routing rules layered on top: events carry structured content and metadata, and rules decide which subscribers receive which events based on that content, instead of every subscriber receiving everything published to a topic. This is the natural fit once a system has many event types and many consumers, each interested in only a subset.
Streams
A stream is an ordered, durable, replayable log of events, retained for a configurable window instead of removed once consumed. Multiple consumers can each read through the same stream independently, and a consumer added later can replay history it wasn't around for. Streams are the right fit for continuous, ordered, high-volume event data (clickstreams, sensor readings, an audit trail) where the sequence and the ability to reprocess history both matter, versus a queue's simpler "each message handled once, then gone" model.
Decoupling and the guarantees that come with it
The core benefit across all of these is decoupling: the producer of a message and its consumer don't need to run at the same time, at the same speed, or even both be up simultaneously. That benefit brings a specific set of new problems that a direct, synchronous call never had to solve.
- Retries. If a consumer fails to process a message, it needs to be retried, usually with exponential backoff rather than immediately and repeatedly.
- Dead-letter queues (DLQs). A message that keeps failing after a bounded number of retries gets moved to a separate dead-letter queue instead of being retried forever or silently dropped, so it can be inspected and reprocessed manually rather than blocking or looping the main queue indefinitely.
- Idempotency. Most messaging systems guarantee "at least once" delivery: a message can arrive more than once, usually because a consumer processed it successfully but the acknowledgment was lost. A consumer has to be written so that processing the same message twice produces the same end result as processing it once, by checking whether an order was already fulfilled before fulfilling it again, for instance.
- Event ordering. Some systems guarantee messages are delivered in the order they were sent (usually only within a partition or a specific ordering key); others make no such guarantee. Whether an application needs strict ordering, and how much throughput it will trade for it, is a decision to make explicitly, because ordering constraints limit how much can be processed in parallel.
Compare: messaging services across the three major clouds
| Concept | AWS | GCP | Azure |
|---|---|---|---|
| Queue | SQS | Pub/Sub (or Cloud Tasks for task-style work) | Service Bus |
| Pub/sub | SNS | Pub/Sub | Service Bus (topics) / Event Grid |
| Event bus / routing | EventBridge | Eventarc | Event Grid |
| Streams | Kinesis | Pub/Sub (streaming mode) | Event Hubs |