Progressive Overload and Incremental Migration
You don't add 40kg to the bar overnight, and you don't rewrite a system in one go — small, steady, measured increases win both times.
On this page
Progressive overload is the oldest rule in strength training: to keep getting stronger, make the work slightly harder, regularly — one more rep, a slightly harder lever, a few more seconds in the hold. Jump too far and you stall or get hurt. Never increase it and you stop adapting.
Migrating a system works the same way.
The big-bang rewrite is the 40kg jump
A full rewrite asks the organisation to absorb an enormous load at once: freeze features, rebuild everything, switch over on a single date and hope. It’s the equivalent of loading the bar with your goal weight on day one. Sometimes you get away with it. Usually something gives — a deadline, a team, or the old system you were “nearly” done replacing.
Incremental migration is the training plan
The strangler fig pattern is progressive overload for software: route one small slice of traffic or one screen to the new implementation, measure, then increase the load.
- Small increments. One route, one component, one consumer at a time.
- Measure every session. Error rates, latency and bundle size are your rep counts. If the numbers drop, you don’t add load this week.
- Keep both running. The old system is your spotter until the new one can hold the weight on its own.
- Deload on purpose. Every few increments, stop adding features and consolidate: delete dead paths, pay down the shortcuts, update the docs. Tendons adapt slower than muscles, and organisations adapt slower than code — more on that in Deloads Are Tech-Debt Sprints.
Choosing the next 2.5 kg
In the gym the smallest plate decides how gently you can progress. Migrations have plates too, and the more sizes you have, the smoother the ramp:
- Feature flags let you move one user, one team or one percentage of traffic at a time.
- Routing rules at the edge or in the app shell send one path to the new implementation and everything else to the old one.
- Dual-running — reading from both and comparing, or shadowing writes — lets the new system carry the weight without anyone depending on it yet.
- Adapters that keep the old API shape mean consumers don’t all have to move on the same day.
Pick the smallest increment that still teaches you something. One internal screen with low traffic is a warm-up set; the busiest checkout path is a max attempt.
Failed reps and RPE
A failed rep isn’t a disaster; it’s information. In a migration, a failed rep is a rollback — and it should be just as unremarkable. If rolling back is scary, the increments are too big.
Lifters rate effort with RPE (rate of perceived exertion): how many more reps you had in the tank. An error budget is a migration’s RPE. If this week’s increment burned most of it, don’t add load next week. If it barely moved, you can afford a bigger step.
And stalls are data. When a lift stalls for three sessions, a good coach changes something — volume, technique, sleep — rather than just trying harder. When a migration stalls at “80% moved”, the remaining 20% is usually the hard part in disguise: odd consumers, undocumented behaviour, a team with no time. Treat it as a new problem, not a motivation issue.
Where I’ve used it
When I replaced a commercial graph library with our own, we didn’t swap it in one release. We matched the old API closely enough that screens could move across one at a time — see the case study.
Where the metaphor breaks
Muscles don’t have dependants. When you add load to a system, other teams feel it, so increments need communicating in a way your training log never does. And unlike a lift, a migration has a finish line: the old system must eventually be switched off. Plan the final, unglamorous increment — deleting the old path — as deliberately as the first.
Takeaways
- Have lots of plate sizes: flags, routing, dual-running, adapters.
- Make rollback as boring as a failed rep.
- Use an error budget as RPE to decide whether to add load.
- Treat stalls as information, and schedule the deletion of the old system.
The lesson from the gym holds: consistency beats intensity. Small, boring, measured increases compound.
- #migration
- #strangler-fig
- #training-principles
- #tech-debt
- #feature-flags
- #error-budgets
↩ Linked from (6)
To make adoption painless we kept the public API close to the library we were replacing. That let teams move screen by screen instead of all at once — progressive overload for a codebase.
It's the same insight as Progressive Overload and Incremental Migration, from the other direction: increase load steadily, and give the slow-adapting parts time to catch up.
Related: Progressive Overload and Incremental Migration is the other half of the same programme — small increases, then consolidation. Hypertrophy and Skill Phases: Build vs Harden Cycles zooms out from the week to the q…
Small and steady beats heroic. It's progressive overload for a codebase. No big-bang rewrite, just a little more load each week, and it never blocked feature work. Ratchet, don't promise. A rule that prevents regressions…
- Front Lever LeverageGrowing
…by ego. Pick the progression you can hold with a straight line, then make the lever slightly longer. Classic progressive overload. Accumulate time in short holds: several 5–10 second holds beat one shaky 20. Train the p…
Training resources I used: a touch-typing course to learn the technique properly, then little and often on typing race sites. Improvement at higher speeds is slow and gradual — very much progressive overload.
↪ Links to (2)
Related by topic
- Growingmetaphor
Golden Paths and the Recommended Routine
Calisthenics Lab - Growingcase study
Building a Low-Code BPMN Workflow Platform
Frontend craft - Growing
Calisthenics Programming: Skill vs Hypertrophy Phases
Calisthenics Lab - Seed
Convex
Frontend craft