Event-driven architecture connects components through events: immutable records that something happened — an order placed, a payment captured. Producers publish to a broker and move on; consumers subscribe and react independently. Where asynchronous messaging moves work off the request path, this style defines the system’s topology by subscriptions: the tenth consumer attaches exactly like the first.

Event-driven architecture: the Order Service publishes an OrderPlaced event to an event broker; three subscribed services react independently, and a Fraud Check Service added later attaches by subscription without changing the producer.

The diagram shows the fan-out of one event type; in a running system, consumers often publish further events of their own, forming chains.

How It Works

  • A component completes a local state change, then publishes an event naming the fact in past tense (OrderPlaced) to a broker topic.
  • The broker delivers the event to every subscriber; each consumer runs its own logic — update a projection, notify a user, start a follow-on process — and may publish further events.
  • Event notification carries only a reference, and consumers call back for details; event-carried state transfer embeds the data.
  • The event schema is the public contract. Producers evolve it backward-compatibly, because they cannot enumerate their consumers.

Failure Modes

  • A “minor” schema change breaks consumers the producing team never knew existed — the schema is the coupling surface.
  • A consumer emits an event that re-triggers the original producer; the feedback loop floods the broker (event storm).
  • At-least-once delivery duplicates events; consumers without idempotent handlers double-charge or double-notify.
  • A silently failing subscriber falls behind; growing lag turns bounded staleness into unbounded drift.

Verification

  • Consumer-driven contract tests run every subscriber’s expectations against the producer’s schema in CI; a breaking change fails the producer’s build.
  • Replaying redelivered events against each consumer produces side effects exactly once.
  • Consumer lag per subscription stays under its threshold; an alert fires on the age of the oldest unprocessed event.
  • CI diffs a generated subscription map (who consumes which event) against live broker configuration.
  • Asynchronous messaging provides the transport beneath the style — queues, retries, dead-letter handling.
  • CQRS projects events into read-optimized views.
  • Choreography-style sagas coordinate distributed transactions purely through events, adding compensation on failure.
  • Event sourcing is the persistence-side counterpart: within one component, the event log is the system of record and current state derives from replay — a decision independent of how components communicate.

References