Tacnode™
Glossary
Data Patterns

What Is the Single-Writer Principle?

The single-writer principle is a concurrency design rule: each item of mutable state has exactly one owner, such as one thread, process, service or agent, that performs every write to it. Others may read the state or send the owner requests to change it, but never write it directly. Because only one writer mutates the state, writes need no locks or compare-and-swap retries, and the owner puts conflicting requests in order instead of letting them collide.

Updated

What is the single-writer principle?

Martin Thompson set out the principle in a September 2011 post, Single Writer Principle, on his Mechanical Sympathy blog. His definition: "The Single Writer Principle is that for any item of data, or resource, that item of data should be owned by a single execution context for all mutations." His argument was about cost: contended writers queue on locks or retries. In his table, incrementing a 64-bit counter 500 million times took 300 ms on one thread and 118,000 ms on two threads sharing a lock.

Thompson was on the team at LMAX, a retail financial trading platform, and co-created its Disruptor. Martin Fowler's July 2011 write-up, The LMAX Architecture, attributes the conclusion to that team: "to get the best caching behavior, you need a design that has only one core writing to any memory location." Fowler adds that "queues fail the one-writer principle."

Thompson applied it beyond CPU cores: "If a service, in SOA architecture parlance, is the only service that can write to its data store it can be made to scale and perform much better." In distributed systems it shows up as one owning service per dataset, one actor per entity, or one consumer per log partition. Kafka assigns partitions "so that each partition is assigned to exactly one consumer in the group," per the KafkaConsumer documentation, so keying events by entity gives each entity one writer at a time.

How the single-writer principle works

Take a refund budget that several support agents draw on. One owner holds the budget; the other agents send it requests:

python
# One owner per budget. Other agents send requests; they never write the budget.
def budget_owner(budget_id, inbox):
    remaining = load_remaining(budget_id)     # only the owner holds this value
    for req in inbox:                         # requests are applied one at a time
        if req.amount <= remaining:
            remaining -= req.amount
            record(req, "approved", remaining)
        else:
            record(req, "rejected", remaining)

Two requests that would overspend the budget together can't both be approved: the owner applies them in turn against the value it holds. Nothing is locked, because nothing else writes.

The principle leaves three problems to the design. Throughput per key: every write to a hot item goes through one owner. Ownership handoff: after a failover, a paused old owner can wake up and write. Martin Kleppmann's answer is a fencing token, "simply a number that increases (e.g. incremented by the lock service) every time a client acquires the lock," which storage uses to reject the stale owner. Readers: the principle governs writes only, and readers of a replica or projection see a copy that lags the owner.

Why the single-writer principle matters in real-time systems

The principle has found a new audience in AI agents, which act concurrently with no person putting their actions in order. Cognition's April 2026 essay Multi-Agents: What's Actually Working, by Walden Yan, recalls that parallel agents' choices "often conflicted with each other, leading to fragile products," and concludes that "multi-agent systems work best today when writes stay single-threaded and the additional agents contribute intelligence rather than actions." For agents, the rule becomes one authoritative writer per shared state: one agent or service owns the plan, budget or task status, and the others propose.

It works best when state partitions cleanly by owner. When many actors act on the same total, such as a budget spent from several channels, the owner becomes a serialization point every request passes through. The alternative is a transactional store as arbiter: writers commit directly, and the store rejects the conflicting one. For decision state Tacnode holds, such as holds, per-agent limits and agent actions, writes are serializable transactions, so conflicting commits cannot both land, and readers can query the latest committed state rather than a projection. More on the coordination patterns is in multi-agent coordination.

FAQ

Related terms

Further reading