I am one of those engineers who find improving deployment strategies catnip. At a previous company I set up a system where we get a change from our machines to prod in under 15 minutes. That included reviews, packaging, full testing, smoke testing with production data, canary deployment, automatic rollbacks, etc. Most companies don’t seek that level of efficiency, but in the age of AI, they are discovering the bottleneck was never the code, but the friction of deploying it. There is a problem when an AI agent can write a fix in 4 seconds, but can only validate the fix in 4 days and get it to the customer for feedback in 4 weeks.
The Karpathy autoresearch loop showed how agents can write code at machine speed, but only in a sandbox. In contrast today's human-gated deployment pipeline was built to stop humans from breaking 2004-era Java monoliths. The Darwin Loop is a deployment architecture derived from first principles: minimize Entropic Action by reducing state-transition cost and complexity so iteration frequency can increase. This architecture, while faster for humans, is built for agents iterating at machine speed and unlocks the evolutionary dynamics needed for Recursive Self-Improvement.
Death by a Thousand Flags
A cited “best practice” for software deployment is the following:
Wrap a change in a feature flag and test locally.
Open a PR, get review/tests, merge to main.
Branch main for release, build, test, and canary-deploy.
Enable the flag, roll it out, and review metrics.
Iterate if problems arise; otherwise remove the flag.
Unfortunately with this “best practice” for some teams it can take months to get a change out. Feature flags were made to reduce the failure blast radius, but they laundering complexity and bring problems of their own, including:
Wrapping is manual, not always done, and rarely complete.
Flags become a shadow VCS with unbounded debt.
2^N states make reasoning/testing impossible.
Three loops (PR, deploy, toggle) slow every change.
Flags reused over and over to bypass infrastructure overhead.
Some flags are permanently partially deployed or never removed.
The joke, but not joke: do you have a feature flag to remove a fully deployed feature flag?
The 2^N possible states turn database migrations and schema changes into high-stakes puzzles with no obvious safe path.
How did we get here?
We evolved our way here. Code reviews, unit tests, reproducible builds, canary releases, each layer tried to reduce the cost of a change if it went wrong. Two metrics drove everything:
Uptime: Deployments that bring down the site threaten revenue.
Deployment frequency: Releases contain features; delayed releases decrease revenue and decreases understanding about customer usage.
Feature flags will always exist because the business needs to be able to turn on and off full features. Maybe to delay a marketing campaign or to only allow features to specific customers such due to regional laws. When turning off a flag is faster than doing a release, pressure to wrap all changes in flags increases. This leads to Kate’s 15th software law:
Kate’s 15th software law: As deployment velocity approaches zero, reliance on runtime feature flags approaches infinity.
Bespoke release processes that tried to solve this also reflected their environment:
Mobile apps have a long external review cycle, so QA is staffed to catch errors before release.
Facebook’s “Move Fast and Break Things” used an hourly release train with canary deployment and automatic rollbacks. This worked in PHP, but as binaries and complexity grew, they eventually introduced a feature flag system.
Uber let engineers put changes into production so they could use them in the physical world, but only they can access it.
You could potentially engineer your way out of each problem such as designing a language with built-in revision control and concurrent phenotypes. But to find the actual solution, we need to return to first principles.
The Thermodynamics of Shipping Code
Every deployment has a cost, and that cost comes from three things1: how expensive the change is to make, how complex the system is, and how often you’re willing to try.
ξ: (Transition Cost) the cost of moving code from a developer’s mind to production execution. The literal CPU hours, Slack notifications, and manual approvals to get a commit live.
K: (Complexity) the structural complexity, the number of microservices or interconnected state systems that could break.
f: (Frequency) how frequently customers could get new changes.
A company releasing once per decade (f=0.1) will likely be outcompeted by one releasing yearly (f=1). The uptime and deployment frequency metrics map directly to ξ and f. Early Facebook iterated fast (f) because PHP was simple (K) and cheap to deploy (ξ) with hourly releases and automatic rollbacks.
Feature flags fail catastrophically: they increase ξ (flag-flipping, monitoring, cleanup) while masking K (burying 2^N complexity inside branches). The system appears to manage risk but accelerates internal cost, something only FANG companies can subsidize.
Most teams already know where their ξ and K are too high and what is causing their f to be slow. The engineers who fix them usually start by noticing patterns like these:
Before: A change waits a week for review because one person “has to” sign off. After: They wrote a test that exercises the condition, deleted the human gate, and the same change gets approved in twenty minutes.
Before: Flaky tests turn every CI run into a dice roll. After: They quarantined the flakes, fixed the root cause (a race in the test harness, not the code), and time from PR creation to merge drops by a week on average.
Before: “No Deploy Friday” became “only deploy Tuesday” became “batch for next month.” After: They added automatic rollback on error rate spike, deleted the policy, and found their incident rate didn’t change, but their feature velocity tripled.
Before: A dormant flag collided with a new change and caused a Sev-1. After: They set flags to auto-expire at 30 days; if no one extends it, the flag dies and the collision becomes impossible.
Before: Staging went down and fifty engineers went home early. After: They gave every engineer an ephemeral environment spun from their branch; “staging is down” became a non-event.
Ideal Architecture for Software Iteration
Agents can write code at machine speed. We need them to deploy at machine speed too. From first principles: maximize delivery velocity while minimizing total entropic cost.
Zero-Hysteresis Rollbacks (ξ → 0): A failed change simply ceases to exist. Zero cleanup, zero mutation, zero state pollution.
Single-Variable Universes (K → minimum): Test in absolute isolation. Exactly one variable in flight, not 2^N. No branching, no dead paths, no state debt.
Single-Loop Iteration (f → maximum): One continuous loop from code to production feedback. No separate PR, deployment, and flag-flipping cycles fragmenting f into discrete, expensive steps.
This is the architecture evolution already uses. In biology an organism expresses a variant; if it is fit, it propagates. If it is unfit, it dies. Organisms don’t validate in a simulation, but through increasing stages: can the DNA run? Can it find food? Can it grow? Then, can it mate?
The Darwin Loop
Changes progress through ever-increasing exposure, from successfully building to responding to live traffic. A survival filter continuously monitors health and only successful changes persist and propagate.
Survivorship Filter: Let Production Decide
The goal is to minimize cost and risk to the substrate. Like most deployment systems, this means verifying the build, running tests, then using mirror traffic, then actual production traffic. Each step increases potential cost.
Here is where the Darwin Loop diverges:
Promote on validation, not on schedule. Once a change passes pre-production validation, there is no new fitness signal in waiting for a release date.
Deploy to minimal exposure. If the only fitness signal is “does not crash on start,” survival may require only a single instance and a 200 from the healthcheck endpoint.
Leave successful changes alone. A passing change stays live at whatever fraction of deployment it earned even if this is only 0.1%. New deployments replace the oldest, so production becomes a continuously evolving fleet of experiments.
The survivorship filter does not shepherd releases. It collects signals to kill what should not exist, including binaries previously assumed fit. It is also self-filtering: a binary that detects its own failure can self-select out before the filter acts.
The Fitness Function
Because every release must be measured for fitness, objectives are defined in a mathematically precise, machine-evaluable form. Elevated from deployment plumbing to a critical business tool, they become the single source of truth for product requirements, replacing the scattered organizational memory of Jira, Slack, and OKRs. They should span the full lifecycle: build latency, test coverage, resource efficiency, correctness, and customer-facing behavior. More signals mean sharper selection. What counts as a signal is itself a design problem, but that’s a separate essay from the architecture that consumes them.
With this in place, a Red Queen can be introduced: a co-evolving adversary that probes deployed binaries for novel failure modes such as security vulnerabilities, edge cases, resource exhaustion and records each discovery. For most this starts simple with fuzzing, something AI can’t hack around like it can with unit tests.
Reproduction: How Good Code Spreads
Source Reproduction:
A change reproduces only after receiving enough positive signals. For example, it then automatically merges into the main branch. Even if deployed to only 10% of machines, it eventually spreads to all of production as new changes incorporate and propagate it.
Binary Reproduction:
Newer, validated variants systematically replace the oldest changes. This bounds the half-life of any release without the latest changes, driving the population toward optimal fitness. This can even work without a centralized push: idle deployments check their own age and automatically request a replacement deployment.
Evolving State:
Stateful components still need coordination, but there is no need to go back to release trains. There are many possible alternatives such as a binary stating that they need the fleet at version X before it can be deployed.
No “main” release, no deployment train
Even if changes are merged into main, there is never a release from a branch called “main.” Deploying main is not only superfluous, but implies a gatekeeper that owns the release when every change is already owned.
Once we have no need for a central main branch release, we can explore more powerful paradigms. In evolutionary biology, Muller’s Ratchet shows that a single, asexual lineage is a genetic dead end, doomed to accumulate deleterious mutations until it collapses under its own entropy. Species survive through genetic recombination: beneficial mutations from different lineages combine and spread while bad changes are purged. Even if GitHub privileges one branch by default, Git itself has no special branches. The Linux kernel operates this way: module and distribution owners merge from each other, and no single branch is sacred.
For agents iterating at machine speed, we can take this further. At the simplest, new changes start from a branch based on two healthy branches running in production: start from Parent A, merge in Parent B.
On the Dwarkesh Patel podcast, Andrej Karpathy noted that LLMs currently have no equivalent to AlphaGo-style self-play, no innate mechanism for beneficial variations to recombine and compound. Without it, naive self-improvement loops inevitably suffer from model collapse: Muller’s Ratchet manifesting in weight space.
Karpathy’s own autoresearch loop illustrates the gap: it generates hundreds of experiments and retains winners, but nothing combines two independent winners into a third. It also validates against a fixed eval script rather than live signal, so it optimizes toward whatever the script rewards without a Red Queen. Autoresearch nails single-loop iteration, but misses recombination and adversarial pressure, the difference between fast and evolvable.
The Darwin Loop makes software evolvable.
Recursive Self-Improvement with AI
Once deployment cost is minimized, the system can modify, test, and deploy its own changes. If objective metrics live in a separate repository, an AI has explicit, measurable targets to optimize against.
Most discussions of Recursive Self-Improvement focus on models improving their own weights. This architecture can do that, but the mundane applications matter more. A new crash at 2am. Before the on-call engineer is notified, an AI writes a fix, deploys it to 10% of production, and verifies it survives. By 9am it had propagated to 50% of the fleet. The human reviews it over coffee. A human is no longer needed to shepherd a change through release.
When human signoff is required, it can happen at any point such as before promotion to live customer traffic. Once given, everything downstream still happens automatically.
Engineering Capacity
Many repositories only need a few changes a month. The more time spent shepherding changes, the less time is free for work that matters. Human shepherding is entropic action: it burns human attention and produces no fitness signal. Reduce the shepherding time, and the same engineer can respond to customer opportunities, sales opportunities, and the insights that only appear when you can iterate fast enough to discover what actually works.
Conclusion: The Thermodynamic Advantage
This might feel like science fiction compared to what many are using at work. Many have felt the pain of current “best practices” intimately but lacked the math to describe why. The Darwin Loop is the evolution of my older 15-minute pipeline and even before AI, the speed was wonderful to experience as an engineer.
Others have written about this future, but usually as a research curiosity about how to evolve code, not deliver code. They then go back to wrapping changes in feature flags. The Darwin Loop recognizes that the delivery layer is already a fitness function. There are many reasonable ways to build this, but they will all have the same shape dictated by the math: minimize ξ, minimize K, maximize f. Doing that improves human velocity just as much as agent velocity. An AI can write a fix in four seconds; the architecture that gets it to a customer in four minutes instead of four weeks is not science fiction. It is buildable now.
This framing comes from my work exploring the physics of systems. I’ve mapped the thermodynamic concepts from my preprint on Informational Energetics: Entropic Action here to software terms.

