A database row can tell you that an order is cancelled. It may not tell you what the customer originally requested, which decision changed it, or what another service had already done. Sometimes that missing history is inconvenient. Sometimes it is the central problem the product must solve.

That distinction is a better starting point for event sourcing than a preference for a particular architecture. Ask what the business needs to explain after the fact. If the answer is simply “show the latest value,” a conventional database model may be entirely appropriate.

Name facts that matter

An event should describe something that happened in the domain. DeliveryAddressChanged communicates more than RecordUpdated. It gives a future reader a reason for the change and gives downstream code a useful fact to interpret.

Imagine a booking that moves through requested, confirmed and cancelled states. Storing those transitions can support a timeline, a customer-support investigation and a separate availability view. The event history is useful because those questions exist. Recording every field edit without a purpose mostly creates more data to maintain.

Before implementing anything, write three questions that require history. Then sketch the events needed to answer them. If the connection is weak, reconsider the model.

History creates responsibilities

An append-only record does not remove difficult decisions. Events need stable meanings. Concurrent writes need rules. Consumers need to cope with older event versions, duplicate delivery and partial failure. Personal information needs a deliberate lifecycle rather than an assumption that everything can remain forever.

The go-mink toolkit provides building blocks for this work: an event store, optimistic concurrency, projections and versioning support, among other capabilities. A library can handle mechanics, but it cannot decide what “confirmed” means in your business. That belongs in the product model and its tests.

Start with one boundary

A sensible first experiment is one workflow with a clear owner and a real need for explanation. Model a few meaningful events, build one read view and test a conflicting update. Rebuild that view from the event history. Check what happens when a consumer stops halfway through processing.

Keep unrelated parts of the application simple. A settings page or content catalogue does not need to adopt the same persistence pattern just because a booking workflow benefits from it.

The useful outcome is an understandable system whose history answers concrete questions. Event sourcing is one way to get there. The questions should come first.

Have a thought to add?Let’s keep talking