Lesson 6 / 25
Thin vs Fat Events, Domain vs Integration Events
Choose how much data an event carries and which events cross service boundaries.
How much to put in an event
A thin event carries identifiers only (OrderPlaced { orderId }); consumers call the source for details. It keeps events small and data fresh, but couples consumers back to the source's API and availability, and can cause a burst of calls after every event. A fat event (event-carried state transfer) carries the data consumers need; they work independently and can build local copies, at the cost of larger events, a wider contract and copies of data that must be governed (including personal data). Also separate domain events, used inside one service's model and free to change, from integration events, published for other services, which are stable, versioned and deliberately designed. Do not publish every internal state change: publish the business facts other contexts actually need.
Thin and fat versions of the same fact
Choose per use case; many systems settle in between.
// thin: consumers must call GET /orders/o-1001
{ "type": "OrderShipped", "orderId": "o-1001" }
// fat: consumers have what they need
{
"type": "OrderShipped",
"orderId": "o-1001",
"customerId": "c-42",
"carrier": "BlueDart",
"trackingNumber": "BD123456789IN",
"shippedAt": "2026-10-03T09:10:00Z",
"items": [{ "sku": "notebook", "qty": 3 }]
}Watch personal data in fat events
Events are copied into logs, topics, data lakes and consumer databases. Include personal data only when consumers need it, and plan how a deletion request reaches every copy.
Quick check: What is a drawback of thin events?
- Consumers must call back to the source for details, coupling them to its availability
- They are always larger than fat events
- They cannot carry IDs
- They break schema registries
Answer
Consumers must call back to the source for details, coupling them to its availability — Thin events push consumers to query the source, reintroducing runtime coupling.