Skip to content
The Scale Ladder: One Agent to One Hundred Thousand

The Scale Ladder: One Agent to One Hundred Thousand

It’s easy to mis-state a scale target in a way that sounds precise but isn’t. “One team, one chip project, twenty engineers, each running twenty agents” sounds, in casual translation, like “twenty users, twenty agents each” — a team-scale, multi-tenant framing. But a far more common real case is different and worth distinguishing precisely: one person running several concurrent Claude Code sessions against a shared personal memory store, not a team of twenty sharing infrastructure. Those are different problems wearing similar-sounding descriptions, and designing for the wrong one wastes real effort in both directions — over-engineering the small case, under-engineering the large one.

That kind of mix-up is exactly the failure mode this article exists to prevent. “Concurrent multi-agent memory” is not one design problem with one right answer. It’s several distinct problems that happen to share a name, each with a different actual bottleneck, and conflating them produces designs that are simultaneously too heavy for what you have today and too flimsy for what you’re planning toward. The fix is a ladder: name the tiers explicitly, say what breaks first at each one, and — this is the part that’s easy to skip — say plainly which tier a given piece of machinery is for, so nobody imports Neo4j’s locking model to solve a problem git already solves for free.

Four tiers as a rising staircase, each labeled with its writer count, its actual bottleneck, and its fix — a mkdir lock at tier 1, a real transactional database at tier 2, sharding and an honestly speculative telemetry loop at tier 3

Tier 0: one writer, no problem

The baseline, worth stating precisely because it’s the case most existing personal AI-memory tooling actually lives in: a single process, writing to its own store, one operation at a time. There is no concurrency problem here to solve. Git’s sequential-commit model already handles the one failure mode a lone serial writer has — losing an update mid-write — and it handles it for free, with no additional infrastructure. Every purpose-built database’s concurrency machinery — MVCC, write-ahead logs, quorum replication, fine-grained locking — exists specifically to coordinate multiple simultaneous writers, or writers against readers, safely. None of it is engaged by exactly one writer. Adopting any of it at tier 0 means importing complexity to solve a problem that doesn’t exist yet.

This sounds obvious stated directly. It’s violated constantly in practice, usually by reaching for “the right tool” — a vector database, a graph database, an embeddings index — before checking whether the problem the tool solves is actually present.

Tier 1: one user, several concurrent agents

This is the first tier where a real concurrency problem exists, and it’s closer than most personal AI tooling assumes. Run ps aux | grep claude on a machine with an active Claude Code habit and it’s common to find four, six, more processes: interactive sessions in different terminal tabs, background subagents, a daemon or two. Every one of those processes can, in principle, write to the same shared memory store in the same few-second window. That’s not a hypothetical team-scale future — it’s the actual, present-tense state of a single engineer’s own laptop.

The standard, sufficient answer at this tier is not a database. It’s a portable, dependency-free mkdir-based mutex around the specific few lines of code that read-modify-write a piece of shared state — because mkdir is atomic on POSIX filesystems — it either creates the directory or fails with EEXIST, with no window between checking and creating — which makes it a correct lock primitive without needing flock (not preinstalled on macOS) or any external dependency at all. This isn’t a hypothetical remedy; it’s a well-established, boring primitive, exactly the reason it’s the right tool here rather than something more exotic.

That’s the tier-1 lesson stated generally: the bottleneck at “one user, several agents” is specific, narrow critical sections — a handful of read-modify-write operations that need mutual exclusion — not a systemic need for distributed-systems infrastructure. A lock around the dangerous few lines beats a database rewrite, because the actual concurrency at this tier is low (single digits, bursty, all on one machine), and the failure mode (a lost counter increment, an occasional retry) is cheap to fix directly.

Tier 2: a small team

Scale the same shape up by people, not just sessions: call it twenty engineers on one verification team, each running some number of agents against a shared project knowledge base. This is the scenario the friend’s conversation that opened this series actually described, once correctly parsed — not twenty users each isolated with their own twenty agents, but one team’s infrastructure absorbing writes from everyone on it simultaneously. Realistic concurrent-writer counts land somewhere in the tens to low hundreds, not the thousands.

This is where the crossover into real database machinery earns its keep, and it’s worth being precise about why, because the reasoning generalizes better than the specific numbers do. The honest threshold isn’t a volume of writes — it’s a count of simultaneous writers. Below some writer-count, one process at a time is ever actually touching a given piece of state, and a lock (or git’s sequential commits) resolves the rare collision cheaply. Above it, collisions stop being rare enough for a lock held for milliseconds to be a reasonable strategy, and you want a system built to let genuinely concurrent writers proceed without blocking each other by default.

That’s what Postgres’s MVCC model actually buys, and it’s worth stating in the vendor’s own terms rather than paraphrasing: reading never blocks writing, and writing never blocks reading, true even at the strictest isolation level, with row-level conflicts detected and resolved automatically rather than requiring a human or agent to manually reconcile a diff. Qdrant’s storage layer takes a related but distinct approach — every write goes through a write-ahead log that assigns a sequential number, and conflicting updates resolve by simply discarding whichever one has a lower sequence number, no locking involved at all. (That single-global-sequence picture is the single-node case; a distributed, multi-replica Qdrant setup resolves conflicts with per-peer clocks instead of one global order — the simplification holds for illustrating the mechanism, just don’t carry “one sequence number” into a cluster design.) Weaviate leans on tunable quorum replication, where a write always lands on every replica but the client can choose how many acknowledgments to wait for before it’s told the write succeeded. None of these mechanisms is “better” in the abstract. They’re different answers to the same underlying question — what happens when two writers touch overlapping state at nearly the same instant — and at tier 2’s writer counts, having a real answer instead of an ad hoc lock starts to matter.

It’s worth making “collisions stop being rare” concrete rather than leaving it as an intuition, because the underlying math is the same shape as the birthday paradox and it’s genuinely counter-intuitive. A lock held for even a few milliseconds only matters if two writers actually try to acquire it inside that same narrow window. At tier 1’s handful of writers, the odds of that happening inside any given few-millisecond slice are low enough that waiting it out is cheap. But the probability of some collision happening across a full working session doesn’t scale linearly with writer count — it scales roughly with the square of it, the same reason a room of twenty-three people has better-than-even odds two of them share a birthday even though there are only three hundred and sixty-five days to choose from. Twenty engineers’ worth of agents isn’t “twenty times as many collisions as one engineer’s.” It’s closer to four hundred times the pairwise opportunities for two writers to land in the same narrow window — the birthday framing is an illustrative analogy for that quadratic shape, not a rigorous derivation of lock contention (a proper model is arrival-rate and hold-time, closer to a queueing argument, and one that assumes independent, uniformly-distributed writers, which bursty agent activity at session start won’t actually be). The analogy is worth using for intuition precisely because the real math is harder to state simply, and it’s honest to say so: near saturation, real queueing wait times blow up considerably faster than a clean quadratic curve suggests, which if anything makes tier 2’s upper end riskier than this picture shows, not safer. That’s exactly why a mechanism that was comfortably cheap at tier 1 turns into routine contention well before tier 2’s writer count reaches anything that sounds large in isolation.

A curve of pairwise collision opportunities against writer count, growing quadratically rather than linearly — flat and cheap through tier 1’s single digits, then rising sharply through tier 2’s tens

Tier 3: production, hundreds of thousands of writers

This is the tier this series is actually designing for, and it’s worth being honest that it’s a different kind of problem than tiers 1 and 2, not just a bigger version of the same one. At this scale, the writers aren’t only agents. A regression suite reporting a new failure signature is a writer. A telemetry pipeline bucketing errors by root cause is a writer. A human filing a correction is a writer. Multiply realistic per-engineer agent counts by an organization’s actual engineer count, add every automated system that has something worth recording, and six figures of concurrent readers and writers stops being a hypothetical stress test and starts being the actual operating condition a production system has to survive on an ordinary day.

Put a real number on tier 3 instead of gesturing at “production scale.” A hundred engineers, each running a hundred concurrent agents during working hours, is ten thousand agent-driven writers before a single automated system gets counted. Add the writers a later article in this series argues belong in this picture just as much as agents do: CI firing on every commit across however many repositories that org maintains — a single commit alone fans out into a dozen-plus CI-job writers — nightly regression suites reporting results test by test, and sanity bots polling continuously. A nightly run alone can be thousands of individual test-result writes, landing inside roughly the same few-hour window every single night, across every active repository at once. None of this requires an exotic enterprise scenario; it’s the direct, linear extrapolation of the same ps aux | grep claude observation that motivated tier 1, multiplied by a headcount and a CI schedule. A write volume computed this way isn’t something any single database instance was ever built to serialize, regardless of which one — the ceiling isn’t one vendor’s configured default, it’s the plain fact that one machine has a finite number of CPU cores, connection slots, and disk IOPS. A system operating at this scale needs sharding, or federation, or some architecture where no single node is expected to serialize transactions from every writer in the system — which is a genuinely different design problem than “which database has good locking,” and one later articles in this series will have to engage with directly rather than gesture past.

Why the ladder matters more than any single rung

The point of laying out four tiers explicitly isn’t that each one needs its own bespoke solution written from scratch — it’s that every design decision in the rest of this series needs to state, plainly, which tier it’s solving for. A mkdir lock is the right answer at tier 1 and actively wrong advice at tier 3. Postgres’s MVCC is overkill at tier 0 and load-bearing at tier 2. A single instance’s connection and throughput ceiling is irrelevant trivia at tier 1 and a hard architectural constraint at tier 3. None of these facts contradict each other — they’re all true, at their own tier, and the only way to build something coherent across the full range is to keep saying, out loud, which rung of the ladder a given piece of the design lives on.

The rest of this series climbs the ladder deliberately: the concurrency models a tier-2 team would actually reach for, the harder problem of writers that aren’t agents at all, and the telemetry and invalidation mechanisms a tier-3 production system needs that tiers 1 and 2 can mostly ignore. Keeping the tiers separate is what keeps the eventual reference architecture from being either a toy that only works on one laptop or a distributed-systems fantasy with nothing concrete underneath it.

Last updated on