One event, many independent consumers. Publishers don't know who's listening; subscribers don't know who else is. Decouples producers from consumers so each can evolve independently.
Rendering diagram…
Use pub/sub when an event has multiple interested consumers that can process it independently:
user.signed_up — email, analytics, CRM, provisioningorder.placed — inventory, billing, shipping, notificationdocument.uploaded — virus scan, OCR, archive, notify ownerdeployment.completed — status dashboard, Slack, on-callIf you're adding if (thing) doA(); if (thing) doB(); if (thing) doC(); in the same function, you want pub/sub.
A publisher emits events to a topic without knowing who's listening. Subscribers register interest in the topic and receive every event independently. Common backends: Kafka, RabbitMQ, AWS SNS/SQS, Google Pub/Sub, Redis Streams.
Each subscriber processes events in its own isolated lane. One subscriber's failure doesn't block the others. One subscriber's slow processing doesn't slow the publisher.
Events should describe what happened, not what to do. user.signed_up is good. send_welcome_email is not — it's a command dressed as an event, and it violates the decoupling.
Version the schema (user.signed_up.v1) and keep events self-describing. A subscriber should be able to handle an event without calling back to the source system.
Every subscriber will see every event at least once. Duplicates are normal. Make subscribers idempotent using the event ID.
Don't have subscribers share a queue. Fan out from the topic into per-subscriber queues so slow consumers don't block fast ones and failures are isolated.
Adding a new optional field: safe. Removing a field: breaking. Renaming: breaking. Publish v1 and v2 side-by-side for a migration window; retire v1 when no subscribers are consuming it.
Every subscriber should emit "lag" — how far behind the latest event it is. A subscriber that's been 10 minutes behind for an hour is silently broken.
invoice.approved, not approve_invoice.Periodically check an external system for changes and trigger workflows when new or updated records are detected. The reliable alternative when webhooks aren't available.
Receive real-time events from external systems via webhooks, validate them, and trigger the appropriate workflow response. The foundation of reactive automation.