Serverless
Intermediate 15 min read Serverless

Event-Driven Architectures

Publish facts, subscribe to outcomes

EDA decouples producers from consumers via a bus: SNS/EventBridge, Event Grid, Pub/Sub. Producers publish facts; consumers subscribe. Delivery is at-least-once, so idempotency and retry/poison handling are contracts, not features.

event busSNSEventBridgePub/SubEvent Gridat-least-onceidempotency
Before we start

What you will learn

  • Model events as domain facts with schema + versioning
  • Route events with filters rather than fan-out code
  • Design idempotent consumers and poison-message handling
In 60 seconds

A producer publishes an event to a bus; the bus fans it to matching subscribers. Services stay decoupled: adding a consumer is a config change, not a code change in the producer.

Introduction

What is this?

Bus types: SNS (topic, pub/sub), EventBridge (event bus + rules + targets/schedules), Azure Event Grid (topic + subscriptions + filters), Pub/Sub (topic + push/pull subscriptions). Event shape: envelope (metadata, source, detail-type) + detail incl. JSON schema + version. Routing: filter on source/type/attributes; dead-letter / DLQ per subscriber; retries (exponential, bounded). Delivery: at-least-once ⇒ duplicate possible ⇒ consumer idempotency (dedupe key). Ordering: generally not guaranteed cross-partition; SQS FIFO/Event Grid partial ordering differ. Pattern taxonomy: events, commands, queries; saga/outbox vs choreography.

Motivation

Why do you need it?

  • Decoupling lets teams ship consumers without touching (or coordinating with) producers.
  • Bus provides buffering, retries, and fan-out — no bespoke scaling code per integration.
  • Event audit trail doubles as a change log for downstream systems.
  • Adding a cross-team consumer becomes a subscription + schema version, not a PR into a monolith.
Think about it

Mental model

Imagine

A radio station broadcasting, listeners tune in when they care

Think of

Event bus pub/sub

The station (producer) doesn't know its audience; each listener (consumer) subscribes, filters, and can join or leave without the station changing anything.

Mechanics

How it works

  • Producer validates + publishes a versioned structured event.
  • Bus applies subscriber filters and routes to matching targets.
  • Each target tries delivery with retries; failures land in a DLQ.
  • Consumers process; duplicates possible → consumer keying/idempotency.
  • Consumers scale independently; back-pressure is per-queue.

Event flow.

Producer
Bus
Analytics
Email
Inventory
DLQ
Hands-on

Examples

Declarative routing idea (cloud-agnostic)

Declarative routing idea (cloud-agnostic)
rule "order-events":
event * source=orders type=order.*
target analytics.sink() target notify.fanout()
# consumers upgrade schema independently
type order.created → v2: order-id, items[] (was: ids)

Routing and filtering live in the bus config; consumers own their interpretation of the versioned schema.

Real world

In production

  • Order pipeline: order.created → inventory, billing, search-index, analytics concurrently.
  • Multi-service fan-in to one warehouse: all domain events → lake loader.
  • Asynchronous notification flows: user.signup → welcome email + fraud check.
  • Saga compensation via outbox: emit command events, orchestrator coordinates.
Guidelines

Best practices

  • Emit facts (order.cancelled), not commands (sendEmailToUser).
  • Monotonic scheMAS: add fields, rarely remove; version major changes explicitly.
  • Make consumers idempotent: dedupe on event id or a deterministic business key.
  • Give every subscriber its own DLQ and alert on DLQ depth > 0.
  • Set sensible retry policies: exponential with jitter, bounded attempt count.
Watch out

Common mistakes

  • Treating the bus as a message queue; both exist, don't blur them.
  • Synchronous fan-out in producer code instead of using filters.
  • Consumers ignoring duplicates, then 'we charged twice' incidents.
  • Tightly coupling schemas so every producer change is a consumer release too.
When things break

Debugging tips

  • Inspect the bus's dead-letter queue first; most 'missing events' die there.
  • Replay a single event from the bus (EventBridge replay, SNS/DLQ redrive).
  • Spawns two identical schemas with different namespaces → filter typo case.
  • Tracks event-id vs processing-id: dedupe collisions vs real drivers.
Interviews

Interview checkpoint

Practice

Hands-on lab

Fan-Out with a Bus and Prove Idempotency
45 min · intermediate
In progress
Objectives
  • Publish one event to two consumers via a bus
  • Configure filters and a DLQ
  • Hardware-proof duplicate-safe processing with a dedupe key

Fan-Out with a Bus and Prove Idempotency

45 min · intermediate

0/3 steps
0%
sandbox · Linux sandbox
$
Try these commands
Test yourself

Quick quiz

0/2
1

Default cloud event delivery is:

2

Adding a new consumer in EDA typically requires:

Go deeper

Official documentation