Skip to content
matthewcm.dev

    ↑ ↓ move · ↵ open · tab scopeopen graph →

    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.

    Growingmetaphortended planted 3 min read
    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

    ↪ Links to (2)