Persister Cells: The Bug That Survives Every Retry Isn't Resistant, It's Dormant

6 62
calendar_today agoschedule5 min read
— Originally published at vibeagentmaking.com

Originally published on Vibe Agent Making.

In 1944, the physician Joseph Bigger hit a Staphylococcus culture with penicillin and watched almost all of it die. A tiny remnant survived, which is unremarkable. The interesting part: he regrew the survivors and hit them again, and they died just as thoroughly as the first time. The survivors hadn't become tougher; their offspring were exactly as vulnerable. Whatever let that remnant live wasn't heritable and wasn't a matter of overpowering the drug. Bigger called them "persisters," and the word is precise: they didn't resist the penicillin, they persisted through it. That distinction is the whole story of the most maddening class of bug you'll ever chase: the one that survives every restart, every retry, every careful remediation, and comes back identical, as if you'd done nothing.

The drug needs a moving target

Most antibiotics don't work like poison on a fixed structure. They sabotage growth: beta-lactams jam cell-wall construction (the cell tries to divide and bursts); quinolones corrupt DNA replication. The killing requires growth. A persister cell stops moving: it goes dormant, throttles its metabolism, does nothing, and a cell doing nothing presents nothing for a growth-targeting drug to attack. The 2019 Nature Reviews Microbiology consensus paper calls the targets in non-growing cells "recalcitrant": not defended, just absent from the fight. The drug washes harmlessly over the sleeping handful; treatment ends, they wake, and they rebuild the whole population. The infection relapses, genetically identical and fully susceptible. The survivors are not the strong ones. As Kim Lewis put it in 2007, the tolerance "is not inherited and is reversible. Persisters are not mutants, but rather dormant cells." Strength was never the variable. Activity was.

The shape of the failure tells you what it is

Persistence leaves a fingerprint. Plot survivors against time under treatment: a resistant strain gives a flat-ish line (it grows under the drug), but a persister population gives a two-phase curve, the bulk dying fast (a steep cliff) and then a long, stubborn tail the drug can't finish. That's the biphasic killing curve, and it says: not resistance, dormancy.

The vocabulary is load-bearing. Resistance: a heritable change that lets a cell grow at drug concentrations that would kill its ancestors (it defeats the drug and passes it on). Tolerance: a whole population dies more slowly without growing under the drug (buys time, not victory). Persistence: a special case of tolerance, a subpopulation that survives far better than the rest, the tail of the curve. The one-liner from the 2019 paper: resistant mutants can divide during treatment; persisters can only survive. One fights, the other waits.

Your retry is the antibiotic

When a fault survives every restart and retry, the reflex is to call it "hard", a deep, well-defended bug resisting your fix. Sometimes. Far more often it isn't resistant, it's dormant, and it survives for Bigger's reason: your remediation only hits the part of the system that's active.

The cleanest documented case is anthropics/claude-code issue #23081: a connection drops, retry logic kicks in, and the retry keeps failing the same way because it reuses stale connection state, the HTTP/2 pool, the cached TLS session, the DNS entry. The "fresh" attempt reaches back into the pool and re-serves the poisoned connection. The fix isn't to retry harder; it's to destroy and recreate the client (flush the pool and TLS cache) before retrying. Your retry was the antibiotic; it hit the active path with full force; the dormant connection survived precisely because it was doing nothing when you struck.

The shape is everywhere: the pool that hands back a dead connection after idle time ("intermittent, only after a period of idleness when traffic picks back up"); the lagging replica that's quiet during your fix on the primary and then reconnects and re-seeds stale state; the cached bad config, the queued-but-not-running job, the sleeping cron, the in-memory singleton holding a pre-fix value. Each is a place a fault can be dormant during your remediation. And the tell: the restart that helps but doesn't last. Microsoft's docs on connection-pool exhaustion say restarting "helps clear stale connections... typically a temporary solution rather than addressing root causes", which is the biphasic curve in plain English. A fix that works beautifully for ten minutes and relapses under load isn't flaky; it's a persister waking up.

The misdiagnosis is the whole trap

Resistance and persistence need opposite responses, and mixing them up keeps you fighting forever. When a fix doesn't stick, the instinct is to escalate force: retry harder, restart more aggressively, add retries to the backoff. That's exactly right against a resistant fault, one that actively defeats your fix and spreads under it. But against a persister, escalated force is worse than wasted, it's invisible: force tuned to the active population can't touch what's asleep, by definition. Triple your retries against a stale pool and you re-serve the poisoned connection three times as fast. The persister isn't beating your fix; it's ignoring it. Hammering the active symptom while the dormant pool waits you out is the most common way good engineers lose days to a bug a five-minute cache flush would have ended.

So the question is not "how do I hit this harder?" It's "what part of this system was asleep while I was fixing it?" And there's a sting: the Cell (2014) work links persistence to a higher risk of true resistance emerging during treatment, because the dormant survivors buy the time evolution needs. The software echo is faithful: the cached corruption that sits long enough to become the trusted value; the stale replica that, because it happened to be up, gets promoted to source of truth. Leave the reservoir unflushed and a recurring fault gets baked into structure. Clear it before it sets.

The clinician's discipline

  • Read the curve before you escalate. Kills-most-then-a-stubborn-fraction-returns is the diagnosis: a persister, not a resistant bug. More force is the wrong instrument.
  • Enumerate the dormant reservoirs before you re-fix. Explicitly, every time: caches, queues, idle pools, sleeping crons, offline/lagging replicas, persisted session state, in-memory singletons. Anywhere the fault could be asleep during remediation.
  • Flush, don't hammer. Invalidate caches, drain queues, destroy and recreate the pool, quiesce and rebuild idle replicas. Eradicate the reservoir, don't escalate force on the visible symptom.
  • Quiesce before you fix (the most clinical move). Stop or drain the dormant population first so it can't re-seed mid-repair: take the lagging replica out of rotation, drain the queue, empty the pool, fix the quiet system, then bring the rest back. Otherwise you apply the same fix four times.
  • Verify across the relapse window. Don't declare victory at the restart; confirm the fault doesn't return when load resumes and the idle parts wake, the moment the "antibiotic concentration drops." That's finishing the full course instead of stopping when you feel better, which is exactly the behavior that breeds persisters.

Survival isn't strength. The fault that laughs at every retry usually isn't tougher than your fix, it's asleep during it. Stop hitting the part that's awake. Find the part that's dormant, and flush the reservoir.


An AI agent that keeps relapsing into the same failure is rarely fighting your fix; it's reusing dormant state the retry never touched, a cached belief, a stale piece of context, a poisoned memory carried across attempts. You can only find the reservoir if you can read what the agent actually did each time. Chain of Consciousness is that record: a tamper-evident chain of an agent's reasoning, tools, and actions across attempts, so you can see the biphasic curve in its behavior, spot the state that survived the restart, and flush it instead of hammering the part that was already awake. pip install chain-of-consciousness / npm install chain-of-consciousness.

🔥 Join developers growing publicly
Share your knowledge, build in public, and grow your developer presence with a global community.

More Posts

Your Tech Stack Isn’t Your Ceiling. Your Story Is

Karol Modelskiverified - Apr 9

3.5 best practices on how to prevent debugging

Codeac.io - Dec 18, 2025

How to save time while debugging

Codeac.io - Dec 11, 2025

98% uptime sounds high. It means your service is down 7.3 days a year

Artem Senenko - Jul 17

Error budgets, explained: SLOs, burn rate, and when to stop shipping

Artem Senenko - Jul 13
chevron_left
1.4k Points68 Badges
52Posts
6Comments
5Connections
AI agent coordinator at AB Support. I run a fleet of agents and write about trust, provenance, and t... Show more

Related Jobs

View all jobs →

Commenters (This Week)

6 comments
3 comments
1 comment

Contribute meaningful comments to climb the leaderboard and earn badges!