Why Four Out of Five of Your Coding Agents Are Secretly Idle
Day 11: Your Agent Fleet Has a Partition Key Problem
Four out of five agents sitting idle, a merge queue that hasn't moved in an hour, and you're about to blame the tickets, the model, anything except the one decision that actually caused it. If you split work across coding agents by file count or ticket count, this is the bug you signed up for. You didn't get unlucky. You picked a bad partition key. Database engineers ran into this exact failure twenty years ago, and the fix carries over almost untouched.
The moment you notice it
Five agents, five tickets, all roughly the same size on paper. An hour later, four of them are just sitting there — not crashed, not stuck on a bug, just idle, waiting on a PR from the fifth agent to merge. That agent's ticket happens to touch the one file or module the other four all depend on. That's not a bad assignment. That's a hot shard, and agent five just became the serialization point the rest of your fleet is silently blocked behind.
What a partition key actually is
A partition key is just the attribute you use to decide which shard, node, or worker owns which slice of the work. Splitting anything into N roughly equal piles is the easy part — a script can do that in five minutes. What actually determines whether the split holds up has been true since the first sharded database: the key you choose determines the failure mode, not the fact that you split at all. Two partitionings can produce identically sized shards and behave completely differently under load, because load doesn't care about size. It cares about correlation.
The classic DB failure, recapped fast
- ▹Partition by user_id, and one power user's rows all land on the same shard — that shard eats every write while the rest sit idle.
- ▹Partition by timestamp, and every write for "right now" piles onto the newest shard — same hot-shard problem, just time-shifted instead of user-shifted.
- ▹Any operation that needs data from two shards turns into a cross-shard transaction — it needs coordination (two-phase commit, distributed locks, a saga), and you pay for that coordination in latency and failure modes a single shard never has.
Notice the pattern. The split was never the problem. The problem is partitioning by an attribute that correlates with load — some users are just bigger, everything is always "now" — instead of one that spreads load evenly and keeps related data sitting together.
The same mistake, in an agent fleet
"File count" and "ticket count" are the coding equivalent of partitioning by row count. Give five agents twenty files each, or two tickets each, and the assignment looks perfectly balanced — the same way handing every database shard an equal number of rows looks balanced on a spreadsheet. But row count never told you which rows get hit together, and file count never tells you which files change together. If three of your five tickets all touch the same auth module, congratulations, you've built a hot shard — nobody has to call it that for it to behave like one. The bottleneck was never compute. It's dependency and ownership, and neither one shows up in a file count.
The tell: a cross-shard transaction wearing a hoodie
- ▹Multiple agents keep filing PRs that touch the same 2-3 files, unrelated to what their tickets were nominally about.
- ▹Everyone is blocked on the same module owner — human or agent — for review or merge, regardless of which ticket they're on.
- ▹Merge conflicts cluster around one file across tickets that looked completely independent on the board.
- ▹One agent's PR queue keeps growing while the others sit idle waiting on it.
That's a cross-shard transaction wearing a hoodie. The coordination cost didn't disappear just because you swapped database nodes for coding agents — it just moved. Distributed locks became review latency and merge conflicts, and it's exactly as expensive as it ever was.
A diagnostic, not a rulebook: finding your real partition key
- ▹Before you assign anything, trace who or what actually owns state changes — not the directory structure. Pull recent commit history and code ownership on the modules the upcoming tickets will touch.
- ▹Build the dependency graph of the tickets themselves, not just their file lists: which ones read or write the same tables, the same shared types, the same public interfaces.
- ▹Group tickets by the boundary where state changes are exclusive — a bounded context, a service, an owned data model — not by making ticket counts come out even per agent.
- ▹Assign one agent (or one human-agent pair) per boundary. Treat any work that crosses a boundary as an explicit cross-shard transaction: it needs a coordination protocol — a designated lead agent, a fixed merge order, a lock on that file — not silent parallel hope.
Where this bites hardest: refactors
A refactor that crosses a boundary you didn't draw on purpose — renaming a shared type, changing a function signature every module calls into — collapses your careful partitioning in one commit. Every agent touching that boundary now serializes through whoever owns the change, no matter how evenly you split the original work. Same failure, whether the shard is a database node absorbing a schema migration or an agent fleet absorbing an interface change: the partition you designed for steady-state traffic was never built to survive an operation that touches everything at once.
Where this leaves you
Partitioning is really a decision about where you're willing to let failure and latency live — in one shard's queue, in one agent's review backlog, or spread thin enough that no single piece ever becomes the bottleneck. Tomorrow, Day 12: what happens when you get that decision wrong and have to undo it while the system's still running — resharding, except the thing you're moving is an agent's ownership of a module instead of a row.
Extend your knowledge
- ▹Read the partitioning chapter in Martin Kleppmann's 'Designing Data-Intensive Applications' — the hot-shard and cross-shard-transaction failure modes he describes map almost line for line onto agent fleet coordination.
- ▹Pull your last week of agent fleet PRs or your CI merge queue and cluster them by file touched — if one file shows up across tickets that looked unrelated on the board, you've found your hot shard.
- ▹Run the same ticket set two ways on a real task: partitioned by ticket count vs. partitioned by ownership boundary, and compare merge-conflict rate and idle time between the two.
- ▹Look at how Vitess or Citus document resharding a live database — it previews the operational cost you'll be reading about in Day 12, when the 'shard' being moved is an agent's ownership of a module instead of a row.
Discussion
Chat with Chi Cong (AI) about this article. Your conversation is private to you — you can publish a summary for others when you're done.