Concepts

Event store

Talk to an event store expert ↗

Most databases keep the answer. They store how things are right now, and every update overwrites what came before. When the business later asks how it got there, that history is gone.

An event store keeps the history instead. Every change is recorded as an immutable event, in order, and current state is derived from it. A purpose-built event store also checks each new event against that history before accepting it, so business rules hold at the moment of the write.

DATABASE · CURRENT STATE
One row, overwritten

Each change replaces the last value. The row says where the student is today, not how they got there.

IDSTATUSCOURSESCITY
s-1registered0Amsterdam
0 earlier values are gone for good.
EVENT STORE · EVERY CHANGE
An ordered history, appended

Each change is an immutable event, written after the last one and never written over.

1,204,326StudentRegisteredstudent:s-1
1 of 1 events kept, in order, for as long as the history matters.

This page explains what an event store is, how Axon Server stores, retrieves and validates events for applications built on Axon Framework, and how it compares with the databases and platforms teams often use instead.

What is an event store?

An event store is a database that records every change in an application as an immutable, ordered event. Instead of storing the latest state of a customer, an order or an account, it stores the sequence of facts that produced that state, and keeps them for as long as the history matters.

Three operations make a database an event store. It stores every change by appending it after the last one, never writing over it. It retrieves one entity’s history quickly, even out of billions of events. And it validates every append against the history already recorded, rejecting a fact that contradicts it.

01 · STOREAppend, never overwrite

Each change goes after the last one. Recorded events are closed.

1StudentRegisteredCLOSED
2CourseCreatedCLOSED
3CourseSubscribed
4AddressChanged
5CourseSubscribed
02 · RETRIEVEOne entity, out of billions

An index picks out only the events about the entity at hand.

student:s-10 of 2,400,000 read
03 · VALIDATECheck before accepting

A new event that contradicts the history is rejected.

#course c-9: capacity 30
#30 students subscribed
new: CourseSubscribed s-41 to c-9 ?
Any database can hold events. These three operations make it an event store, and they have to hold under production load.

What is an event?

An event is a record of something significant that happened, named in the past tense: StudentRegistered, PaymentRejected, AddressChanged. Events are facts, so they are never changed afterwards. When circumstances change, a new event is appended after the old one. Each event carries its type, its position in the store, when it was recorded, the identifiers or tags that link it to the entities it concerns, and its payload.

TYPE
CourseSubscribed
POSITION
1,048,577
TIMESTAMP
2026-11-05T09:14:22.318Z
TAGS
student:s-1course:c-9
PAYLOAD
{ "studentId": "s-1", "courseId": "c-9", "semester": "2027-spring" }
TYPEWhat happened, in the past tense

Named for the business fact, not the technical change. Handlers and queries select on it.

HISTORY OF student:s-1
StudentRegisteredcity: Amsterdam
CourseSubscribedcourse: c-9
CourseSubscribedcourse: c-4

How is an event store different from a database?

A traditional database stores the answer, while an event store stores everything that produced it. Applications built on event sourcing derive their current state from those events instead of keeping it in mutable rows.

Any database can hold records that describe events, and none becomes an event store by doing so. The name is earned by two operations that have to hold under production load: isolating one entity’s ordered history from billions of events fast enough for a live request, and validating every append against that history at write time.

Keeping history pays off twice. A live application can act on it while a request is still in flight. And when the business asks a question nobody anticipated at design time, the answer is read from the events instead of being wished back into existence.

History also gives auditors and regulators a complete account of what happened and in which order, without a separate audit log that can drift away from the data it describes.

How does Axon Server store events?

Axon Server is built around an append-only log. Its storage is organized in layers, each with one job.

First, events are appended to segment files. Each context has its own event store on disk. New events are written to the end of the current segment, 256 MB by default, and closed segments are never rewritten. Every event receives a position in one global sequence.

Second, indexes find one entity’s history. In aggregate-based contexts, a global index locates an aggregate’s latest event and per-segment pointers lead back to the earlier ones. Dynamic Consistency Boundary (DCB) contexts index events by their tags and types instead.

Third, snapshots live in their own store. A snapshot holds the computed state of an entity at a known position, so loading it means reading the snapshot and only the events recorded after it. Since Axon Server 2026.1, events and snapshots can be sourced in a single operation.

Fourth, older data can move to other tiers. Tiered storage moves closed segments to other storage based on time or size, so primary nodes keep recent data on fast disks while the full history stays available.

01 · SEGMENTSAppend to the log

New events go to the end of the current segment. Closed segments are never rewritten.

segment 1CLOSED
segment 2CLOSED
segment 3CLOSED
segment 4OPEN
02 · INDEXFind one entity

The index points to the latest event, and pointers lead back to the earlier ones.

order:o-7→seg 4 · latest←seg 3←seg 2←seg 1
03 · SNAPSHOTSSkip the long tail

Computed state at a known position, kept in its own store.

order:o-7 @ 800order:o-7 @ 900a snapshot every 100 events
04 · TIERSKeep years of history

Closed segments move off primary disks by age or size.

PRIMARY · FAST DISK
segment 1segment 2segment 3segment 4
OTHER TIER · ARCHIVE
2019 … 2025
Each layer has one job. Together they keep appends cheap, reads narrow, and the full history available for as long as the business needs it.
SOURCINGOne entity, one decision

The index returns only student s-1’s events, folded into current state.

REPLAYAll history, one new question

A cursor reads the whole log in order to build a view nobody planned for.

ONE GLOBAL LOG · EVERY ENTITY5 OF 10 READ
1StudentRegisteredstudent:s-1
2CourseCreatedcourse:c-9
3StudentRegisteredstudent:s-2
4CourseSubscribed · c-9student:s-1
5CourseCreatedcourse:c-4
6CourseSubscribed · c-9student:s-2
7AddressChangedstudent:s-1
8CourseSubscribed · c-4student:s-1
9CourseSubscribed · c-4student:s-2
10CourseUnsubscribed · c-9student:s-1
MODEL · STUDENT s-1
FOLDED FROM 0 EVENTS
registered?
city?
courses?
Fast because it is narrow. Five events about other entities are never touched.

Reading follows the two paths the figure shows. Sourcing reads one entity’s events, bounded and fast, to make a decision. Streaming reads the global log from a tracking token onward, which is how event processors keep projections up to date and how a replay rebuilds a view from the very first event.

How does an event store keep appends consistent?

Every append to Axon Server can carry a condition that the store checks before it accepts the events. If the condition fails, nothing is written, and the application re-reads and decides again. Business rules are enforced at the moment of the write, not by a cleanup job afterwards.

In aggregate-based contexts, the condition is the aggregate’s sequence number: two writers that both read version 41 cannot both append version 42. In DCB contexts, it is an append condition: event criteria over tags and types, plus the consistency marker returned when the events were read. The append fails if any event matching the criteria arrived after that marker.

The second form lets one rule span several entities, such as a course’s capacity and a student’s subscription limit, without sagas and without fixing aggregate boundaries before the first event is written.

AGGREGATE CONTEXTSExpected sequence number

Two writers that read version 41 cannot both append 42.

DCB CONTEXTSAppend condition

Criteria over tags and types, plus the marker from the read.

TWO WRITERS
WRITER AREAD

loaded order o-7 at version 41

WRITER BREAD

loaded order o-7 at version 41

EVENT STORE
40ItemAddedorder:o-7
41ItemAddedorder:o-7
WHAT THE STORE DOES
Both writers decide on the same state.

Is it slow to event source millions of events?

It would be, if applications read every event on every request. They don’t. Snapshots fold a long history into one stored state, so loading an entity with 5,000 events means applying only the events recorded since the last snapshot. Aggregate caching goes further: when the same application instance handles the same entity, its state is often still in memory, and the store only has to verify the append.

NO SNAPSHOTSource everything

Apply every event since the entity was created.

event 1event 5,000
0events applied before the decision
SNAPSHOT EVERY 100Load snapshot, apply the tail

Events 1 to 4,900 are folded into one stored state.

SNAPSHOT @ 4,900
event 1event 5,000
0events applied before the decision
WARM CACHEState already in memory

Same entity, same instance. The store only verifies the append.

IN MEMORY · 0 EVENTS READ
event 1event 5,000
0events applied before the decision
Snapshots buy speed without spending history. All 5,000 events stay in the store, ready to rebuild a snapshot or answer a replay.

Neither layer throws history away. The events underneath a snapshot stay in the store, ready to rebuild snapshots after a bug fix or to answer a replay. Snapshots buy speed without spending history.

How does Axon Server stay available?

In a cluster, Axon Server nodes form replication groups that use the Raft protocol. Each group elects a leader, and an append is confirmed once a majority of primary nodes has stored it, so losing one node out of three costs neither data nor availability. Nodes can also take other roles: secondary nodes hold older data, backup nodes keep copies for recovery, and messaging-only nodes route messages without storing events. Clients reconnect to another node automatically.

01Leader receives the append
02Replicated to the group
03A node goes down
04It returns and catches up
APPLICATIONAxon Framework clientappend event 7
REPLICATION GROUP · 3 PRIMARY NODESMAJORITY = 2
axonserver-1LEADER

writes event 7

axonserver-2

waiting

axonserver-3

waiting

An append is confirmed once a majority of primary nodes has stored it. Losing one node of three costs no data and no availability.

What does Axon Server add as an event store?

Axon Server brings the pieces teams otherwise build around a general-purpose database into one system.

01

Consistency on every append, per aggregate or across entities with Dynamic Consistency Boundary.

02

Fast per-entity reads out of billions of events, through dedicated indexes and snapshots.

03

High availability through Raft-based replication groups and dedicated node roles.

04

Histories that grow for years, with tiered storage moving older segments off primary disks.

05

Routing for commands, events and queries in the same system, so the instance that owns an entity also receives its requests.

TWO SYSTEMSBroker and database, routed apart

The broker does not know which instance holds the order’s state.

AXON SERVERRouting and storage in one system

The routing key sends every command for o-7 to the same instance.

COMMANDS · ORDER o-7
AddItem1
ApplyDiscount2
ConfirmOrder3
ROUTER
Generic brokerround robin
APPLICATION INSTANCES
instance 1
idle
instance 2
idle
instance 3
idle
EVENTS READ0to handle 0 commands
A cache only pays off if the next command finds it. When the system that routes the command also knows where the entity lives, it does.

Why one system
for events and messages

Axon Server is both an event store and a message delivery system, and that is a deliberate choice. Aggregate caching only works when requests for the same entity keep reaching the instance where its state is already warm. Route the command elsewhere and the cache is cold, the application sources from scratch, and the speed the architecture promised is gone.

Splitting storage and routing across two systems means keeping two views of ownership and order aligned with each other, a distributed-systems problem acquired for no benefit. In one system, that knowledge exists once.

The same history also feeds analysis. Axoniq Insights lets data and business teams query event history directly, so a new question does not have to become a new projection.

Talk to an expert

🤔
Frequently

asked
questions

🤔
Frequently asked

questions

What is an event store in simple terms?

A database that saves every change in an application as an immutable, ordered event instead of overwriting current state. It retrieves one entity’s history efficiently and validates each new event against the existing history before accepting it.

Is Kafka an event store?

No. Kafka is a streaming platform built to move events between systems. A producer cannot append on the condition of an expected offset, and reading one entity’s history means scanning a partition. Many teams run Kafka beside an event store: the event store is the system of record, and Kafka carries events outward. See Axoniq and Apache Kafka.

Can I use Postgres or MongoDB as an event store?

At a small scale, yes. Ordering under concurrent writers, a consistency check on every append and efficient per-entity retrieval then become code you build and maintain instead of properties of the storage engine. MongoDB fits well on the read side, holding the projections built from the event store.

How does an event store handle GDPR erasure requests?

Two common approaches keep the record of what happened. Crypto shredding encrypts personal fields with a key per data subject and destroys the key when erasure is required. Event transformation rewrites or removes the affected fields in stored events; Axon Server supports this through Persistent Event Transformation.

Does Axon Server support Dynamic Consistency Boundary?

Yes. DCB contexts have been fully supported since Axon Server 2025.2, existing contexts can be converted since 2026.0, and DCB requires Axon Framework 5. See Dynamic Consistency Boundary.

How do event stores compare?

Many systems can hold events. Fewer are designed around the operations that define an event store. The table compares Axon Server with other purpose-built event stores, event sourcing libraries, general-purpose databases used as event stores, and two systems that are often mistaken for one. It reflects each product’s public documentation as of November 2026.

YesPartialDIY: you build it on general primitivesNon/a or undocumented
SystemBuilt for event sourcingOptimistic appendDCB append conditionsPer-entity readsGlobal orderCatch-up subscriptionsSnapshotsClustering and HAEvent transformationCommand and query routingLicense and hosting
PURPOSE-BUILT EVENT STORES
Axon ServerAxoniqYesYesYes1YesYesYesYesYes2Yes2YesFree tier, paid self-hosted plans, managed cloud
KurrentDBformerly EventStoreDBYesYesPartial3YesYesYesNo, patternYes4Partial5NoSource-available Kurrent License, Kurrent Cloud
EventSourcingDBthe native webYesYesYesYesYesYesNo, patternNo6NoNoClosed source, free up to 25,000 events
UmaDBDCB-native storeYesYesYesYes, by queryYesYesn/a, undocumentedn/a, undocumentedn/a, undocumentedNoMIT or Apache 2.0, self-hosted
EVENT SOURCING LIBRARIES
Marten.NET library on PostgresYesYesYesYesPartial7YesYesPartial, via PostgresYes, maskingNoMIT, runs on any Postgres
Akka PersistenceJVM libraryYesPartial8NoYesNoYesYesYes, Akka ClusterPartial, adaptersPartial8BSL 1.1, Akka platform
GENERAL-PURPOSE DATABASES USED AS AN EVENT STORE
PostgreSQLappend-only tableNoDIY9DIYYes, indexDIY9DIYDIYPartial9DIYNoPostgreSQL License, many managed offerings
MongoDBevent documentsNoDIYDIYYes, indexNoPartial10DIYYes, replica setsDIYNoSSPL, MongoDB Atlas
Amazon DynamoDBevent itemsNoYes, conditionsPartial11YesNoPartial11DIYYes, managedDIYNoProprietary, AWS only
Azure Cosmos DBevent documentsNoYes, ETagPartial12YesNoPartial12DIYYes, managedDIYNoProprietary, Azure only
OFTEN MISTAKEN FOR AN EVENT STORE
Apache Kafkastreaming platformNoNo13NoNo13No, per partitionYesNoYesNo13NoApache 2.0, Confluent Cloud, Amazon MSK
Temporalworkflow persistenceNo14n/an/an/an/an/an/aYesn/an/aMIT, Temporal Cloud

Scroll sideways to see every column.

  1. Axon Server. DCB contexts append with an append condition: event criteria over tags and types plus a consistency marker. Fully supported since 2025.2, and existing contexts can be converted since 2026.0.
  2. Axon Server. Clustering and replication groups depend on the license. Persistent Event Transformation replaces or deletes events in aggregate-based contexts; transformed contexts cannot yet be converted to DCB.
  3. KurrentDB. Multi-stream appends check an expected version per stream. That covers some cross-entity rules, but conditions are stream-based, not tag or query based.
  4. KurrentDB. Clustering requires an Enterprise license from version 26.2.
  5. KurrentDB. Redaction is a licensed, offline, per-node tool. Streams can be deleted or truncated and scavenged.
  6. EventSourcingDB. The documentation states high availability is planned, not yet available.
  7. Marten. The global sequence is a Postgres sequence, which can have gaps. The async daemon tracks a high water mark to handle them.
  8. Akka Persistence. Consistency comes from a single writer per entity through Cluster Sharding, not an expected version from the client. Sharding routes commands to entities, but there is no command or query bus.
  9. PostgreSQL. Expected versions usually mean a unique (stream, version) constraint. Sequences are not transactional, so positions can have gaps and become visible out of commit order. Automatic failover needs external tooling or a managed service.
  10. MongoDB. Change streams give live subscriptions, but resuming depends on oplog retention, so catching up from the first event is up to you.
  11. DynamoDB. Transactions with condition checks across up to 100 items can emulate some multi-entity rules. Streams keep records for 24 hours.
  12. Cosmos DB. Transactional batches are atomic within one logical partition key, and the change feed is ordered per partition key.
  13. Kafka. A producer cannot append on the condition of an expected offset, reading one entity means scanning a partition, and records cannot be rewritten in place.
  14. Temporal. A durable workflow engine. Its event history is an internal log per workflow execution, stored in Cassandra, MySQL or PostgreSQL and capped at 51,200 events. It is not a store for application domain events.

Get Started with Axoniq

Run your event store on Axon Server

Validated appends and fast per-entity retrieval are the operations a general-purpose database makes you build. Axon Server brings storage, consistency, replication and routing into one system, so your team spends its time on the business problem.