Event-driven architecture

Instead of calling each other directly, services publish 'this happened' events and whoever cares reacts on their own time.

something happened, let other parts reactfire and forget notifications between servicespub subpublish subscribeevent driven designevent-driven architechtureemit an event instead of calling the other serviceservices talking through a message bus

See it

Live demo coming soon

What it is

In an event-driven system, code that finishes something publishes a statement of fact ('order.placed', with the order id and total) to a broker, and any number of subscribers react on their own time. The publisher does not know who listens and does not wait for them. Adding a sixth thing that should happen on checkout means adding a subscriber, not editing the checkout function again. Brokers range from Postgres LISTEN/NOTIFY and a jobs table up through Redis Streams, RabbitMQ, SNS plus SQS, Kafka, and hosted tools like Inngest.

Reach for it when one action fans out to many independent reactions (email, invoice, analytics, search reindex, webhook delivery), when the reactions are slow or flaky and should not block the response, or when separate teams and services need to stop calling each other's internals. Events name the past ('user.signed_up'), commands name a request ('send_email'), and mixing the two is how an event bus quietly becomes a very slow function call.

Gotcha: delivery is usually at-least-once, so every handler must be idempotent, because the same event will arrive twice at 3am. Order is rarely guaranteed either. Getting the event out at all is its own problem: publishing to the broker from inside your database transaction is not the outbox pattern and buys nothing, because the broker is a separate system that cheerfully keeps a message you then roll back. Publishing right after the commit is fine when a lost event is recoverable; when it is not, insert the event into an outbox table in the same transaction and let a dispatcher publish it. The bigger cost is debugging: there is no stack trace across the gap, so a dropped event just looks like the email never arrived. Budget for a dead letter queue, correlation ids, and real tracing before you go event-driven, not after.

Ask AI for it

Refactor this checkout flow into an event-driven design using a transactional outbox. On successful payment, in one database transaction, write the order and insert an 'order.placed' row into an outbox table carrying event id, timestamp, order id, amount, and a status column. Do not call the broker inside that transaction: a separate dispatcher polls unsent outbox rows, publishes each to the broker, marks it delivered only on a successful publish, retries failures with exponential backoff, and is allowed to publish a duplicate after a crash. Move the confirmation email, invoice generation, and analytics call into separate subscribers. Make each handler idempotent by recording processed event ids, and route permanent failures to a dead letter queue. Define the event payloads as typed schemas in one shared file.

You might have meant

job queuemessage brokerworkeridempotency

Go deeper