A domain event in the system
A domain event records something that happened in the business, stated in the past tense: OrderPlaced, PaymentCaptured, ShipmentDispatched. It is a fact, immutable once written, describing a change that has already occurred. The past tense is the discipline. An event that reads like an instruction has quietly become a command, and the two behave very differently once they hit the wire.
The term grew out of domain-driven design, where an event names a happening the domain experts care about. Martin Fowler catalogued the pattern alongside the rest of the event family on his site, distinguishing the domain event as a record of a significant occurrence within a model. The naming convention came with it: events are written in the past tense because they assert that something is already true.
Event sourcing pushed the idea further. Greg Young is generally credited with formalising the pattern, in which the stored sequence of events becomes the source of truth and current state is a fold over that history. Young's companion idea, Command Query Responsibility Segregation, separates the model that accepts changes from the model that answers questions. A command expresses intent and may be refused; an event reports a settled fact and cannot be argued with. That asymmetry is the whole point.
Fowler later warned, in his 2017 GOTO talk, that "event-driven" had become four overlapping patterns wearing one label: event notification, event-carried state transfer, event sourcing, and CQRS. The domain event sits underneath all four, which is why teams adopt it without realising which architecture they have signed up for.
A payments service handles a customer paying for an order. The flow starts with a command, CapturePayment, which the service validates against the card and the order total. If it succeeds, the service does not return a status code and forget. It appends a PaymentCaptured event to its log, carrying the order ID, amount, and timestamp.
Downstream, three consumers react to that one fact. A read modelRead ModelEngineeringA DDD read model (query projection)View reference → for the customer dashboardDashboardData & AnalyticsAn analytics dashboardView reference → updates "paid" against the order. The fulfilment context treats the event as a trigger and issues its own command, ReserveStock. The finance context appends a ledger entry. None of them had to be named in the payment service; they subscribed to the event. Months later, a fraud team replays the entire PaymentCaptured stream through a new detection model, possible only because the events were stored as facts rather than thrown away after updating a row.
CapturePayment), addressed to one handler, and allowed to fail. A domain event is the past-tense fact that results (PaymentCaptured), broadcast to anyone listening, and never rejected. The system flows command, then event, then possibly another command.In the Unified Product Graph, a domain event sits in the engineering region as the connective tissue of an event-driven system. It is emitted by the structures that own state (Bounded ContextemitsDomain Eventhierarchy, bounded_context_emits_domain_eventAggregateemitsDomain Eventcausal) and produced as the consequence of intent (aggregate_emits_domain_eventCommandproducesDomain Eventcausal). From there it fans out: it feeds query-side views (command_produces_domain_eventDomain Eventprojected toRead Modelcausal) and can set off further work (domain_event_projected_to_read_modelDomain EventtriggersCommandcausal). Modelling the event as a first-class node, with both its causes and its effects as edges, makes the otherwise invisible choreography of an event system legible: you can trace which command produced a fact and every consumer that woke up because of it.domain_event_triggers_command
Type-specific fields on BaseNode
event_namestringEvent name (e.g. "OrderPlaced")
payload_schemastringPayload schema or shape
triggered_bystringWhat triggers this event
idstringrequiredUnique identifier (UUID)
typeNodeTyperequiredDiscriminator for the entity type
titlestringrequiredDisplay name
descriptionstringOptional detailed description
statusstringLifecycle status
tagsstring[]Freeform tags for filtering
5 edge types connected to this entity.
bounded_context_emits_domain_eventaggregate_emits_domain_eventcommand_produces_domain_eventdomain_event_projected_to_read_modeldomain_event_triggers_command