2. Communicate Facts

Choose immutable event streams over mutable state

Mutable state is not stable throughout time. It always represents the current/latest value and evolves through destructive in-place updates that overwrite the previous value. The essence of the problem is that mutable state treats the concepts of value and identity as the same thing. An identity can’t be allowed to evolve without changing the value it currently represents, forcing us to safeguard it with mutexes and the likes.

Concurrent updates to mutable state are a notorious source of data corruption. While there exist well-established techniques and algorithms for safe handling of updates to shared mutual state, they bring two major downsides. The complexity of these algorithms is easy to get wrong, especially as code evolves, and they require a certain level of coordination that places an upper bound on performance and scalability. Due to the destructive nature of updates to mutable state, mistakes can easily lead to corruption and loss of data that are expensive to detect and recover from.

Instead, rely on immutable state—values representing facts—which can be shared safely as local or distributed events without worrying about corrupt or inconsistent data, or guarding it with transactions or locks.

A fact is immutable and represents something that has already happened sometime in the past, something that can not be changed or retracted. It is a stable value that you can reason about and trust, indefinitely. After all, we can’t change the past, even if we sometimes wish that we could. Knowledge is cumulative and occurs either by receiving new facts or by deriving new facts from existing facts. Invalidation of existing knowledge is done by adding new facts to the system that refute existing facts. Facts are never deleted, only made irrelevant for current knowledge.

Facts are best shared by publishing them as events through the component’s event stream where they can be subscribed to and consumed by others—components, databases, or subsystems—serving as a medium for communication, integration, and replication. Facts stored as events in an event log, new tab in their causal order, can represent the full history of a component’s state changes through time (e.g. using the Event Sourcing new tab pattern) while serving reads safely from memory (called Memory Image new tab).