Mastering Domain Events in Go: Definition, Publishing, and Consumption

This article explains what domain events are, how to define them with proper naming and attributes, explores multiple techniques for publishing events in Go—including parameter injection, static-like helpers, return‑based and repository‑based approaches—and describes strategies for consuming events safely and atomically.

ITPUB
ITPUB
ITPUB
Mastering Domain Events in Go: Definition, Publishing, and Consumption

What Are Domain Events?

Domain events represent facts that have already occurred in the business domain and are important to domain experts. They are defined in the domain layer but are emitted from the infrastructure layer and consumed by application or domain services.

"Events that domain experts care about happening within the domain." – Vaughn Vernon, Implementing Domain‑Driven Design

Defining Domain Events

Domain events should live in the domain package and be named in the past‑tense (e.g., OrderCreated, OrderPaid). Each event must have a unique identifier and a timestamp, and it should also expose the aggregate root identifier it relates to.

Typical interface definition (illustrated in the original diagram):

Specific event interfaces can be created per aggregate, for example OrderEvent and ProductEvent, each extending the generic event interface.

Publishing Domain Events

Four main approaches are discussed:

Pass an EventPublisher as a method parameter – keeps the domain model pure but pollutes the method signature.

Use a static‑like global publisher – in Go this is simulated with a package‑level variable (e.g., var eventPublisher EventPublisher).

Return the event from the domain method – the caller decides when to publish, giving more control over transaction boundaries.

Store events temporarily in the aggregate and publish them in the repository – events are kept in a slice (e.g., OrderEvent []DomainEvent) and flushed after persistence.

Illustrative diagrams for each method are included in the original article:

The author recommends the repository‑based approach for its clear separation of concerns and testability, despite its added complexity.

Ensuring Atomicity

To guarantee that event publishing and aggregate persistence happen atomically, the article suggests storing events together with the aggregate in a single database transaction (the “event table” pattern). An asynchronous task later reads pending events, publishes them, and removes them upon success. Idempotent consumers are essential to handle possible retries.

Consuming Domain Events

Event consumption is treated like handling a special command in the application layer. A DomainEventApp struct contains methods for each event type, receiving a Context and the event, and returning an error to indicate success.

Local consumers register via RegisterSyncEventSubscriber (provided by the DDDCore library), while remote consumers rely on message queues. Because most queues guarantee at‑least‑once delivery, consumers must be idempotent—typically by checking a unique message ID before processing.

Conclusion

The article summarizes the essential characteristics of domain events: they represent immutable facts within the domain, must be named in the past tense, carry enough context for autonomous processing, and should be handled in a way that preserves transactional integrity. The next article will show how to organize a full DDD implementation across application layers.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Backend ArchitectureGoDDDDomain EventsEvent PublishingEvent Consumption
ITPUB
Written by

ITPUB

Official ITPUB account sharing technical insights, community news, and exciting events.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.