ManagementSenior

Release Planning

Release planning is deciding what reaches users, when, and how you will know if it went wrong. The single most useful move in release planning is to stop treating deployment and release as the same event. This page covers that split, the four rollout strategies, the four kinds of feature flag, why rollback is often unavailable, and what to measure.

Key idea
Deploy ≠ release
Measured by
DORA metrics
Elite recovery
Under 1 hour

Deploying is not releasing

Deployment is a technical event: new code is running on production infrastructure. Release is a product event: users can now do something they could not do before. Most organisations treat these as one moment, which is why "release day" carries so much fear — every technical risk and every product risk arrives together, at midnight, on a Friday somebody chose months ago.

Code is deployed to production continuously, arriving switched off behind a feature flag. Releasing is a separate, later and reversible decision: turn the flag on for a small share of users, watch the numbers, then turn it on for everyone — or turn it off in seconds without a rollback.

Separating them changes what a release plan is. Code ships to production continuously, dark and inert behind a flag. The release becomes a separate, reversible decision: turn it on for 1% of users, watch the numbers, turn it on for everyone — or turn it off in seconds without a rollback, a hotfix or a war room.

The four release strategies

StrategyHow it worksRollbackCosts
Big bangEveryone gets it at onceRedeploy the old versionEvery user is the test group
Blue-greenTwo identical environments, switch trafficSwitch traffic back — secondsDouble the infrastructure
CanaryA small slice of traffic first, then widenStop the rolloutNeeds real monitoring to be worth it
Feature flagCode is live but off; toggled per audienceFlip the flag — instantFlag debt if they are never removed

These combine rather than compete, and they operate at different layers. Blue-green and canary decide which version of the code a request reaches — infrastructure concerns, usually owned by whoever runs the platform. Feature flags decide which behaviour a given user gets from that code — a product concern. A mature setup deploys continuously, routes with canary at the infrastructure level, and controls audience with flags at the product level.

Two related techniques are worth naming because they solve problems the four above do not. Dark launching runs the new code path on real traffic without showing anyone the result — you compare its output or its latency against the old path and learn whether it would have worked. Rolling updates replace instances a few at a time, which is what most orchestrators do by default; it is cheaper than blue-green and leaves both versions serving traffic at once, so the code has to tolerate that.

Four kinds of flag, four lifetimes

Teams get into trouble with feature flags because they treat them as one thing. They are not: the reason a flag exists determines how long it should live and who should own it, and mixing the categories is how a codebase ends up with two hundred toggles nobody dares delete.

KindExists toExpected lifetime
Release toggleHide unfinished work so it can be merged and deployed safelyDays to weeks — delete after full rollout
Experiment toggleSplit traffic between variants to measure which performs betterThe length of the experiment, then removed
Ops toggleLet operators shed load or disable an expensive path under pressureLong-lived by design — it is a control, not debt
Permission toggleGive a feature to a plan, a tenant or a group of usersPermanent — this is a product feature, not a release tool

The first two are temporary and the second two are not. Confusing them in either direction hurts: a release toggle left in place becomes an untested code path that quietly rots, and a permission toggle logged as "flag debt" gets deleted by someone doing cleanup, taking the paid tier with it.

When rollback is not available

Release plans routinely list "roll back" as the mitigation for every risk, and for stateless code that is honest. The moment a release touches persistent data, it usually stops being true — and the plan is now describing a safety net that does not exist.

The reason is simple. If version 2 dropped a column, wrote data in a new shape, or consumed a message from a queue, then going back to version 1 does not restore the world — version 1 now meets data it was never written to handle. Restoring a backup loses everything users did since the deploy. This is why experienced teams plan to roll forward: fix and deploy again, in minutes, rather than reverse.

The technique that keeps both options open is expand and contract. Instead of one migration that changes the shape, you do three releases: expand — add the new column while the old one keeps working and both are written; migrate — backfill and switch reads to the new column; contract — remove the old column once nothing reads it. Each step is individually reversible, and the irreversible one happens last, after the new path has been running in production for days.

What a go/no-go should actually check

Where a release decision genuinely needs a moment of judgement, keep the checklist about the things that are not automatable. Whether the tests passed is not one of them — the pipeline already knows, and asking a room of people to confirm it adds delay without information.

  • Is the way back defined — flag off, roll forward, or a rehearsed data path — and has anyone actually done it?
  • What signal would tell us within ten minutes that this made things worse, and is somebody watching it?
  • Who outside engineering needs to know before users notice — support, sales, the people answering the phone?
  • Does anything irreversible happen in this release, and can it be moved to a later one?
  • If it goes wrong at the worst plausible moment, who is available and how are they reached?

Measure the process, not the plan

The DORA research found four measures that together predict both delivery speed and stability — and, unusually for this field, showed that the two are not a trade-off. Teams that deploy more often also break things less often, because small changes are easier to reason about and to reverse.

  • Deployment frequency

    How often code reaches production. Elite performers deploy on demand, several times a day.

  • Lead time for changes

    Commit to running in production. Under an hour at the elite level; months at the low end.

  • Change failure rate

    Share of deployments causing a degraded service. Elite teams sit in the low single digits to about 15%.

  • Time to restore

    How long a degraded service stays degraded. Under an hour is the elite benchmark, and it matters more than avoiding failure.

The pairing is the point. The first two describe throughput and the second two describe stability, and reading either pair alone gives a number a team can improve by making the other worse. A fifth measure — some form of reliability, meaning whether the service met the expectations its users actually have — was added later precisely because a team can score well on all four while the product is unusable.

A caveat worth carrying: these are diagnostic, not a scoreboard. Deployment frequency is trivially gamed by splitting one change into five, and a team measured on change failure rate will simply stop calling things failures. Read them together, and read them against your own trend rather than against someone else's benchmark.

How this shows up in real delivery

The clearest signal of release health is what happens on a Friday afternoon. A team that will not deploy on a Friday is telling you something precise: its rollback is slow, its monitoring will not catch a problem quickly, and recovery needs specific people who are about to go home. The fix is not a Friday policy — it is the recovery time underneath it.

Where it degrades

  • A release board that approves deployments — it adds delay without adding information the tests did not have.
  • Batching a month of changes into one release, which makes every failure hard to attribute.
  • "Roll back" written as the mitigation for a release that runs an irreversible migration.
  • Feature flags with no owner or expiry, which quietly become permanent branches in the code.
  • A canary with no automated comparison, which is a slower big bang with a nicer name.
  • Deployment frequency set as a target, which produces more deployments rather than more value.

When to use it

Use it when

  • You can deploy to production without a manual gate — otherwise start there.
  • Monitoring can tell within minutes whether a change made things worse.
  • Product decisions about who sees a feature need to be reversible.
  • You want to release to a slice of users and learn before committing.
  • Schema changes can be staged so nothing irreversible happens in the same release as new behaviour.

Avoid it when

  • Shipped hardware or client software that users install — the release is genuinely one-way.
  • A regulated release requiring formal sign-off on a fixed, versioned artefact.
  • The team cannot yet remove flags reliably — flag debt will cost more than the flexibility gains.
  • There is no monitoring, which makes a canary release just a slower big bang.

Found this useful?

Share it with someone who is working on the same problem.