StyleChapter II · Styles & patterns · Building block 5 of 8

Event-driven Architecture

An event-driven architecture publishes recorded business facts. Other building blocks respond to this without a direct expiration call by the producer.

  1. EventRecorded business fact.
  2. Event ≠ CommandIt tells what happened, not what to do.
  3. Loose couplingThe producer does not know the recipients.

Context

Why this is important

New reactions arise without changing the producer. An event holds a fact and gives no order. Order does not need to know shipping or invoice. Transport forms and delivery deepen the building blocks Pub/Sub and Outbox.

This building block explains the coupling about business events. For forms of transport and delivery see Queues, Pub/Sub & Streams.

At a glance · Events over a channel

A producer posts an event to the channel, and several consumers react independently.
Shop example · Adding a new reaction

Who needs to change when a reaction comes along?

In modular monoliths, order publishes internally the event OrderPaid. Shipping and invoice respond with their own tasks.

This is how you read the picture

  1. Event In the event mode of the apricot box OrderPaid with "Order ID and time".
  2. Event ≠ Command The event is called OrderPaid, not InvoiceCreate; each module decides for itself.
  3. Loose coupling In event mode, the counter “Changes to order” remains 0Even if there are bearings or key figures.

OrderSets status paid

Code in order

shipment.deliveryPreparation(b)
invoice.proofCreate(b)
  • ShippingPreparation of supply contractsis called upon
  • InvoiceProducing evidenceis called upon
Order is known
2 Modules
Changes to order per new response
1

The flow is readable in one place and the result is immediately visible, but every new reaction changes the order.

Choose coupling and recipient: For direct calls, the code of the order grows with it, in event mode it remains the same (key figures are an illustrative new reaction).

Benefits & limitations

Helps if:

  • Independent reactions to a business change run through events without binding the producer to individual recipients.
  • Messages buffer follow-up work and decouple their processing time from publication.
  • Consumers gain access to the same fact with their own projections or processes without building a synchronous call chain.

Boundaries

  • The flow can become invisible: who reacts to BestellungBezahlt? Keep recipients and progress visible.
  • Eventual consistency: the invoice is created after payment; define what customers see in the meantime.
  • The event schema is a contract with every recipient; changes require Versioning.

In practice

  1. Name events as completed facts and document their schema, identifier and ordering. Consumers can then understand the state without asking the producer to make a decision.
  2. Define progress and failure states for each consumer. Consider a published event processed for business purposes only when the recipient has durably recorded its effect.
  3. Check backlog, retries and ordering for each consumer. Pub/Sub and Streams explores distribution; Transactional Outbox durably records the intent to send.
Read the detailed explanation

A domain event records a change that has already happened. The producer publishes the fact; independent consumers decide on their follow-up work. The producer therefore need not know every downstream component and can complete its own state change separately.

Temporal decoupling makes delays, retries and ordering part of the contract. Publication and successful business processing remain distinct states. Identifiers, versions and progress information make processing traceable across consumers.

Pub/Sub and Streams distinguishes recipient coupling and retention; Transactional Outbox durably records the local intent to publish a change.

Martin Fowler distinguishes four meanings of 'event-driven': Event Notification, Event-Carried State Transfer, Event Sourcing and CQRS. In the shop, BestellungBezahlt is an Event Notification with a small payload: it reports only the order ID and timestamp, and recipients fetch details as needed. Event-Carried State Transfer would be useful when recipients need order data without another request, for example because the source system is not always available for queries.

Check your understanding

Test yourself in three stages

  1. ReadingCheck in the picture

    You switch on the camp in event mode. What changes to the order code?

    View the solution with justification

    Nothing. The counter remains at 0; Order continues to publish only OrderPaid. The camp registers itself as the recipient.

  2. ApplyingTransferred to a new situation

    The creation of documents beats for B-1042 Failed. Who is responding?

    View the solution with justification

    The calculation module in its own reaction, for example with repetition and error state. Ordering and shipping remain unaffected; the team monitors the progress of the invoice.

  3. EvaluateWeighing an alternative

    The team wants to call the event RechnungNunAlsPDFErzeugen. How do you rate that?

    View the solution with justification

    Advantage: The purpose is immediately clear. Disadvantage: It is a command that binds order to the invoice and its format and excludes other recipients. Recommendation: Name orderPaid; the invoice itself decides on the receipt and format.