Event Store vs Database: Choosing State and History

An event store is a database designed to retain a sequence of events. The useful choice is between storing current state as the authoritative record and storing the changes from which state can be reconstructed. A relational database can support either approach.

A subscription table might say that an account is on the Pro plan. An event stream might record when it subscribed, upgraded, cancelled and renewed. Those designs answer different questions. Neither makes an application correct without validation, access control and a recovery plan.

This guide covers that storage decision. For implementation details, use the event-sourcing patterns; for the product, see AllSource's event store database.

Compare the records you need

Requirement Current-state database Event-sourced design
Read today's subscription plan Query the current row Query a derived view or fold the stream
Explain why the plan changed Retain audit records or change history Read recorded domain events and metadata
Correct an earlier mistake Update state and preserve an audit record if needed Append a correction and update the projection
Build a new historical view Depends on the history retained Replay retained events containing the required facts
Delete sensitive information Apply database deletion and backup policies Design payload separation, retention and erasure before ingestion
Recover after an outage Restore backups and recover transactions Recover the log and views; prove acknowledged events survive

An append-only record does not automatically provide regulatory compliance. You still need a policy for personal data, access, retention and backups. A timestamp alone does not establish business ordering across concurrent writers.

One renewal, two useful views

Consider this illustrative domain sequence, rather than an AllSource API request:

[
  {"sequence": 1, "type": "subscription.started", "plan": "basic"},
  {"sequence": 2, "type": "subscription.upgraded", "plan": "pro"},
  {"sequence": 3, "type": "subscription.cancelled"},
  {"sequence": 4, "type": "subscription.renewed", "plan": "pro"}
]

A support view can show the current plan and status. A second view can count cancellations and subsequent renewals. The second view is only meaningful if events distinguish a renewal from a new subscription. Keeping arbitrary JSON forever does not compensate for an event model that omits the business fact you later need.

Before adopting event sourcing, write down a question that current rows cannot answer reliably. Check whether your proposed payloads can answer it. That exercise is more useful than choosing storage from a throughput headline.

When current-state tables are enough

Keep a conventional CRUD model when the product needs current records and ordinary transaction semantics. A small catalogue or internal settings tool may gain little from a domain event stream. Audit tables can record who changed a row without changing the application's source of truth.

A team can also separate read and write code while retaining those tables. That is one form of CQRS; it does not require event sourcing. The CQRS and event sourcing guide separates these decisions with a worked example.

If your existing database already provides the history, concurrency checks and recovery behaviour you need, a second database introduces another operational responsibility. Keep it only if a measured requirement justifies it.

Can PostgreSQL be an event store?

Yes. An application can use append-only PostgreSQL tables for domain events. The design must establish stream identity, ordering, concurrency checks and permissions that prevent accidental mutation. Consumers also need a reliable way to find new events and resume after failure.

The choice is partly about ownership. With a custom event table, your team owns the stream API, consumer progress, replay tooling and compatibility rules. With a purpose-built event store, evaluate which responsibilities the product covers and which remain in your application.

Do not compare a custom table's insert speed with a product's durable append path unless acknowledgement, indexing and persistence settings match. Compare recovery behaviour as well as successful writes.

When an event store earns its place

An event-sourced system is a candidate when accepted business changes must remain explainable and multiple views need to be rebuilt from them. Order workflows, account ledgers and decision histories can have that requirement. A domain label alone is insufficient: an order dashboard might work well with current-state tables and an audit trail.

For agent memory, ask whether a recalled fact must link back to the event that introduced or corrected it. If the requirement is only short-lived conversation context, durable history may add unnecessary work. AllSource's agent-memory approach is a downstream use of event history, rather than the definition of an event store.

What replay cannot promise

Replay reconstructs only what retained events and projection logic can express. It cannot recover facts never recorded. If historical code called an external service without recording its response, replaying that call today may return a different answer.

Use a pure state-building path where possible. Separate it from payments, email and other side effects so rebuilding a view cannot repeat them. Track applied positions and handle duplicate delivery. See event replay and idempotent consumers.

Snapshots can shorten restoration for a compatible view, but cannot substitute for history needed to build a different view. Measure recovery with your event sizes, stream lengths and projection work. No generic latency number establishes your recovery limit.

A bounded evaluation before migration

Use one real workflow and an isolated test environment:

  1. Record accepted changes and their ordering contract.
  2. Build a current-state view and compare it with an independently calculated expected result.
  3. Stop the process after acknowledged writes, restart it and check which events remain.
  4. Rebuild into a separate destination without sending external side effects.
  5. Repeat with duplicate delivery, an incompatible event and concurrent updates.
  6. Record persistence settings, recovery duration, failed cases and operational work required.

AllSource provides an event-replay validation checklist for recording that evidence. Use the API documentation for supported operations and payloads. If a hosted evaluation fits your workload, compare plans before starting a trial.

Further reading

Microsoft's Event Sourcing pattern covers architectural trade-offs. Its CQRS pattern explains separating read and write models, including designs sharing a database.

Write → inspect → query

Store one real event, then query it back.

Start with hosted AllSource, or run the Apache-2.0 core on your own infrastructure. Both use the same event model and APIs.