AWS makes it easy to connect a producer to EventBridge, fan out through SNS, buffer in SQS, and process with Lambda. Every service can be justified individually, yet the complete system may become difficult to trace, replay, and explain. The goal is not to use fewer icons; it is to give every hop one clear responsibility.
Start with the communication contract
An event says something happened. A command asks a specific capability to do something. Mixing the two creates ambiguous ownership. OrderPlaced can have several independent consumers. ChargePayment has an intended owner and a success or failure that the caller cares about.
Use EventBridge when producers should publish domain events without knowing subscribers and routing rules belong in infrastructure. Use SNS for straightforward push fan-out. Use SQS when a consumer needs buffering, controlled concurrency, and independent retry behavior. Lambda is a compute choice, not a messaging guarantee.
Assume at-least-once delivery
Messages can be delivered more than once. A visibility timeout can expire while processing continues, a client can retry a publish, or a service can recover from an internal failure. Consumers need an idempotency boundary based on a stable event or operation ID.
Dead-letter queues are not a failure strategy by themselves. Decide who owns them, which alarms fire, how payloads are inspected safely, and whether replay preserves ordering or triggers outdated side effects. A queue that silently collects failures is delayed data loss.
Put correlation into the envelope
Every event should carry an event ID, type, version, timestamp, source, and correlation identifiers that connect it to the originating request or workflow. Business payloads evolve independently, so consumers should tolerate additive fields and reject unsupported major versions explicitly.
Observe the path, not only functions
Measure event age, queue depth, oldest-message age, retry counts, dead-letter volume, and end-to-end completion time. Function error rate alone can look healthy while a queue grows for hours. Structured logs should include the same event and correlation IDs at every hop.