3. Isolate Mutations

Contain and isolate mutable state using bulkheads

When you have to use mutable state, don’t share it. Instead contain it together with the associated behavior, using isolated and partitioned compartments, separated by “bulkheads” new tab and thus adopting a shared-nothing architecture. new tab This contains failure, prevents it from propagating outside the failed component, limits its scope, and localizes it to make it easier to pinpoint and manage. It also avoids minor issues leading to “cascading failures” and taking down an entire system. For example, recall that validation errors are not failures but are part of the normal interaction protocol of your stateful component.

Bulkheads are most easily installed by having the compartments communicate using asynchronous messaging, new tab which introduces a protocol boundary between the components, isolating them in both time and space. Asynchronous messaging also enables observing the fluctuating demands, avoiding flooding a bulkhead, and providing a unit of replication if needed.

Only use mutable state for local computations, within the consistency boundary of the bulkheaded component—a unit of consistency that provides a safe haven for mutations, completely unobservable by the rest of the world. When the component is done with the local processing and ready to tell the world about its results, then it creates an immutable value representing the result—a fact— and publishes it to the world.

The bulkheaded components should ideally use single-threaded execution to simplify the programming model and avoid concurrency-related problems such as deadlocks, race conditions, and corrupt data. For example, Node.js, new tab Akka, new tab Disruptor, new tab or implementation of the Reactor new tab Pattern and its variants offer this functionality.

In this model, others can rely on stable and immutable values for their reasoning, whereas each component can internally still safely benefit from the advantages of mutability (like the simplicity of coding and algorithmic efficiency), strong consistency (providing ACID new tab semantics), and reduced coordination and contention (through the Single Writer Principle new tab).