Tactical Design with Domain Events

Created on: 9/5/2025

Updated on: 9/21/2025

4 mins

Tactical Design with Domain Events

In our last article we explored aggregates — the building blocks that protect business rules and keep models consistent.
But sometimes, enforcing rules inside a single aggregate is not enough. Actions often have ripple effects across the system.

This is where Domain Events come in.
They let us capture what happened in the business domain and communicate it clearly across different parts of the system.

Designing Domain Events

A domain event represents something meaningful that has occurred in the business.
It should be named in the past tense, reflecting the fact that it has already happened.

Examples:

  • OrderPlaced
  • PaymentConfirmed
  • ShipmentDispatched

When designing domain events:

  • Focus on business meaning, not technical detail.
  • Keep the event data minimal — just enough for other parts of the system to react.
  • Express them in the ubiquitous language so they are instantly understandable to domain experts.

Implementing Domain Events

Domain events are typically raised inside aggregates when important business rules are applied.
For example, when an Order transitions to the “paid” state, it might publish an OrderPaid event.

How these events are handled depends on the architecture:

  • Within the same bounded context, they may trigger changes in other aggregates.
  • Across contexts, they are often published over messaging systems so other teams can react asynchronously.

The key point: events decouple producers from consumers. The order aggregate doesn’t need to know what Shipping or Billing will do with the event — only that the business has declared “Order Paid.”

Using Domain Events

Domain events open up several practical possibilities:

  • Integration – Other contexts can subscribe to events to keep their models in sync (e.g., Shipping reacts to OrderPlaced).
  • Audit Trails – Events form a natural log of what happened, useful for compliance or debugging.
  • Reactive Workflows – Complex processes can be modeled as chains of events instead of tightly coupled calls.

By building around domain events, systems become more modular, scalable, and adaptable to change.

Event Sourcing: Taking Events Further

Domain events can be stored just as messages, but they can also become the primary source of truth.
This is the idea behind Event Sourcing.

Instead of persisting the current state of an aggregate (for example, saving an Order row in a database), we persist the sequence of events that led to that state.
To reconstruct the current state, we replay all events in order.

Benefits of event sourcing:

  • Perfect audit log of everything that ever happened.
  • Ability to rebuild state in new ways (e.g., generating reports from raw events).
  • Naturally aligned with the language of the business.

Challenges of event sourcing:

  • More complex to implement and reason about.
  • Requires careful handling of event versioning and evolving schemas.
  • Not always necessary — often plain domain events with state stored in a database are enough.

Event sourcing is powerful, but it should be applied deliberately. It shines in domains where history matters just as much as current state, such as finance or logistics.

Closing Thoughts

Domain events extend the tactical toolbox of Domain-Driven Design.
They let us capture meaningful business facts, decouple systems, and design workflows that reflect reality more closely.

And for cases where history and traceability are critical, event sourcing takes this idea further — making events the very foundation of state.

Together with aggregates and value objects, domain events complete the picture of tactical design.
They remind us that software is not just about storing data, but about telling the story of what really happens in the business.