State and read models
Entities own durable application state; views build read models from their changes. Their separate responsibilities define where writes are consistent and where reads can lag.
Entities and event sourcing
An entity owns one slice of durable application state, identified by an ID. Its active state is held in memory, while persisted data allows recovery after restarts, movement between nodes, and failures.
Two persistence models
An Event Sourced Entity stores changes as events in a journal and derives state by applying them. Snapshots reduce the history that must be replayed during recovery. Choose this model when the sequence of changes matters or other components need those events.
A Key Value Entity persists its complete current state on each update. It does not retain the event history of an Event Sourced Entity. Choose it when the current value is sufficient.
Both use effects to declare state changes. A successful command reply follows persistence; mutating a field directly does not persist it. Views and consumers can react to the resulting events or state changes.
Ownership and consistency
One owner processes commands for an entity ID at a time within a service cluster. The entity is the consistency boundary: changes within it can be coordinated, while changes across entities require a process or asynchronous reactions.
The runtime routes requests to that owner, passivates idle instances, and recovers them when needed. Distribute writes across suitable IDs rather than putting unrelated data into one large entity.
An entity’s origin is the region where it was created. Its primary region is the region currently accepting writes; the primary can change under the project’s selection mode. Other regions can serve replicated reads, which may lag. Replicated writes using conflict-free replicated data types are an additional Event Sourced Entity option.
Views and CQRS
A view builds a queryable read model from changes to entities, workflows, or broker topics. It lets you query across many instances without making each entity serve that query.
Separate reads from writes
Entities own the write model and validate commands. Views maintain a representation shaped for reads. This separation is commonly called command query responsibility segregation (CQRS).
A view can select fields, combine sources, and maintain several tables for its queries. Its read workload scales independently of the entities producing changes. Use an entity read for the current state of one instance; use a view for filtering, aggregation, or queries spanning instances.
Consistency and delivery
View updates are asynchronous. A query immediately after an entity command can return the earlier state, even when the command succeeded. A view is not a transaction spanning its source entities.
Updates are delivered at least once. For Akka sources, the runtime tracks sequence numbers and removes duplicate updates. Key Value Entity sources can skip intermediate states and provide the latest value. Broker sources need appropriate message identity and ordering.
In a multi-region project, a local view reflects the changes available in that region. Replication lag and projection lag can both affect what it sees.
Changing a projection
A change to the view’s schema or update logic can require rebuilding its data. Plan for the cost of replay and for compatible deployment rather than treating the read model as the authoritative history.
Live query streams deliver updates while connected; they are not a durable substitute for event consumption.
Next steps
-
Implementing Event Sourced Entities and Implementing key value entities implement the persistence models.
-
Implementing Views defines projections, update handlers, and queries.
-
Views documents query syntax and result mapping.
-
Choosing a component type compares state and query responsibilities.
-
Schema evolution covers compatible persisted-data changes.
-
Multi-region operations explains replication and consistency across regions.