← Blog

Staged rollouts: shipping to 1% before 100%

A staged rollout ships a change to a small percentage of users first, then widens that percentage in steps as a metric holds, instead of releasing to everyone in one deploy. 1% today, 10% tomorrow, 100% once the numbers say so.

The failure a staged rollout prevents is specific: a change that passes every test in staging can still break the moment it touches 100% of production traffic, because staging never sees production’s data skew, browser mix, or scale. A rollout that goes straight from 0% to 100% finds that bug the hard way, for every user, at once.

A staged rollout also costs something a dashboard toggle doesn’t: time. That tradeoff is worth naming before you pick your first percentage.

Key Takeaways

  • A staged rollout ships a change to a small slice of traffic, often 1%, then widens it in steps (1% → 10% → 50% → 100%) as a named metric holds.
  • The failure it prevents: a change that passes staging breaks at 100% of production traffic because staging never sees real data skew or scale.
  • Done with feature flags, a staged rollout is one flag whose weight you edit and merge. In dif, dif validate checks the weights sum to 100 before the pull request can land.
  • dif’s bucketing is additive: the same users who were in the first 1% stay in the rollout as it widens to 10%, so nobody flickers in and out mid-rollout.
  • The cost is speed. Rollback means editing the weight back to 0 and merging, so the worst-case kill time is however long your build and deploy take.

What is a staged rollout?

A staged rollout ships a change to a small percentage of users, checks a metric, then increases the percentage in steps until it reaches everyone. Each step is a decision point: the metric either holds and the rollout widens, or it doesn’t and the rollout stops.

The pattern overlaps with the canary release, which Martin Fowler defines as deploying a new version alongside the old one and routing a small, random slice of traffic to it before growing that slice (Fowler, “CanaryRelease”). A staged rollout usually describes the same move from the feature side: not a new service version taking traffic, but a change reaching a growing slice of users, one step at a time.

Why not ship straight to 100%

A change that passes every test in staging can still fail in production, because production has traffic staging never generates: empty carts, untested browsers, slow networks, a currency nobody tried. A rollout that jumps from 0% to 100% in one deploy turns any one of those gaps into an incident for every user at once.

A staged rollout finds the same bug on 1% of traffic instead. If the change breaks, 1% of users saw it, not all of them, and the fix is turning the weight back down before anyone else does.

In practice that’s a sequence of frontmatter edits, not four separate systems: weight 1 becomes weight 10, then weight 50, then weight 100. Each change is a commit, reviewed in a pull request, with the metric from the previous step as the reason to merge the next one.

How to pick your rollout steps

There’s no fixed number of steps; the shape matters more than the count. Start small enough that a bug touches few users (1% on a high-traffic path, higher on a low-traffic one where 1% would take a week to produce a usable sample), then grow geometrically instead of linearly. Going 1% → 10% → 50% → 100% reaches full rollout in four steps, while 10% → 20% → 30% keeps the same step count but exposes three times as many users to an unproven change at step one.

Google’s SRE book describes the same patience for canarying infrastructure changes: run the new version on a small fraction long enough to catch problems that only show up over time, not just at the moment of the request (Google, Site Reliability Engineering, “Release Engineering”). A staged rollout borrows that patience: wait long enough at each step to see a full traffic cycle, a work day or a weekend, before judging the metric. A handful of clean requests in the first five minutes doesn’t tell you what a full day of real usage will.

What to watch at each step

Each step needs a metric to fail on, named before the rollout starts. In dif, that’s the metrics.primary field in the flag’s frontmatter: the one number that has to hold before the next step ships.

Watch two signals at each step: the metric itself (completed checkout, error rate, click-through), and whether the sample is big enough to trust it. 1% of a high-traffic checkout flow might be thousands of users within an hour. 1% of a low-traffic admin page might take a week to say anything. Widening on a vibe before the sample is big enough is how staged rollouts stop catching real problems.

Staged rollouts with feature flags

A feature flag is one way to implement the weight a staged rollout needs, without touching a load balancer or a service mesh. It’s the same conditional code path Fowler described in his toggles article, a flag that reads a variant and runs different code for it, applied to a percentage instead of a binary switch (Fowler, “Feature Toggles (aka Feature Flags)”). The flag’s weight is the step, and widening it is editing a number.

---
id: search-ranking-v3
status: active
owner: priya@acme.com
surface: search
hypothesis: >
  The v3 ranking model holds search click-through at every rollout step.
variants:
  - id: "off"
    weight: 99
  - id: "on"
    weight: 1
metrics:
  primary: search_click_through
created: 2026-10-01
---

## Brief

Staged rollout. 1% now. Widen to 10% once click-through holds for 48 hours,
then 50%, then 100%.

Widening to 10% next week is editing weight: 99/1 becomes 90/10, and dif validate fails the pull request if the two numbers don’t sum to 100. The reviewer sees the diff as two changed numbers, with the metric and the wait time already written down from the first commit. See the .md format for the rest of the frontmatter, and the CLI reference for validate and build.

Widening doesn’t flicker anyone because of how bucketing works: a user’s variant is a hash of their ID and the flag’s salt, recomputed fresh every time instead of stored. That math only moves the boundary and never reassigns someone already inside it, so growing the rollout from 1% to 10% only adds new users. Nobody who was already in the 1% drops out, and nobody gets pulled in and out again on the next page load.

The tradeoff: staged rollouts are slower than a toggle

A staged rollout costs time by design. Each step waits for a traffic cycle before the next one ships, so going from 1% to 100% in four steps, each held for 48 hours, takes over a week before the rollout finishes. A dashboard that could set every user’s traffic to 100% instantly doesn’t need that patience. A staged rollout does, because the wait is what makes the next step’s data trustworthy.

Rollback costs time too. In dif, turning off a bad step means editing the weight back to 0 and merging (the git history is the audit log for why that matters), so the worst-case kill time is however long your build and deploy take. If that’s ten minutes, a bad step at 10% stays live for ten minutes. For a payment path that needs a kill switch in under a second, a merge-and-deploy rollback is the wrong tool for that flag, and a dashboard-based kill switch is the right one there. For most rollouts, where the downside of a bad step is some users seeing a worse result for ten minutes, that cost is the right trade.

Getting started

A staged rollout ships a change to 1% of users, then widens it in steps as a named metric holds, instead of betting everything on one deploy. Pick steps that grow fast enough to finish in days, not months, but slow enough that each one sees a real traffic cycle before the next ships. Name one metric per step before the rollout starts, and know your rollback cost before you need it.

With feature flags as the mechanism, a staged rollout is one file you ramp by editing a number, each change validated in CI before it merges. Install the CLI and scaffold a project:

npm install -g @dif.sh/cli
dif init

See what feature flags are for the fundamentals, and feature flags in your repo for how a staged rollout looks as a reviewed file instead of a dashboard slider.

FAQ

What is a staged rollout? A staged rollout ships a change to a small percentage of users, checks a metric, then widens the percentage in steps until it reaches everyone. It catches problems that only show up on real production traffic before they hit every user at once.

What percentage should a staged rollout start at? Low enough that a bug touches few users: 1% is common for a high-traffic path, higher for a low-traffic one where 1% wouldn’t produce a usable sample in a reasonable time.

What’s the difference between a staged rollout and a canary release? They’re close to the same idea. A canary release is usually framed around infrastructure, a new service version taking a slice of traffic. A staged rollout is usually framed around a feature, a change reaching a growing slice of users. Many teams use the terms interchangeably.

How long should you wait between rollout steps? Long enough to see a full traffic cycle, not just the first requests succeeding. A work day or a weekend is a common minimum, so the metric reflects real usage patterns instead of whoever happened to load the page first.

Can a staged rollout fail safely? Yes, if the rollback is cheap. With a feature flag, rolling back a bad step means setting the weight back down and merging, so the worst case is bounded by how long your build and deploy take, not by how fast someone finds a dashboard toggle.


Sources: Martin Fowler, “CanaryRelease”; Martin Fowler, “Feature Toggles (aka Feature Flags)”; Google, Site Reliability Engineering, “Release Engineering”