Gradual Rollouts: A Step-by-Step Tutorial
Deploying a feature to 100% of users on day one is a gamble. A gradual rollout lets you start small, monitor, and scale up with confidence. If something goes wrong, you roll back to 0% instead of scrambling for a hotfix.
This tutorial walks through the full lifecycle of a percentage-based rollout using feature flags.
What is a gradual rollout?
A gradual rollout (also called a percentage rollout or canary release) is a technique where you release a new feature to a small percentage of users first, then gradually increase that percentage over time.
The key properties:
- Deterministic: The same user always gets the same result. User A doesn’t flip between old and new on every request.
- Adjustable: You can change the percentage at any time. No code changes or deploys needed.
- Reversible: Rolling back is setting the percentage to 0%.
How deterministic hashing works
Under the hood, the flag evaluation engine hashes the user’s targeting key (typically a user ID) together with the flag key. This produces a consistent number between 0 and 100. If that number is below the rollout percentage, the user gets the new feature.
hash("user-123" + "checkout-redesign") → 37
rollout percentage: 10% → 37 > 10 → old experience
rollout percentage: 50% → 37 < 50 → new experience
This means:
- The same user always gets the same result for the same percentage
- Increasing the percentage only adds users, never removes them
- Different flags hash differently, so a user at 5% for one flag isn’t necessarily at 5% for another
Step 1: Create the flag
In Flipswitch, create a boolean flag for your feature. You’ll use the flag key in your SDK code.
For this tutorial, let’s say we’re rolling out a new checkout flow. Create a flag called checkout-redesign with the default value set to false.
Step 2: Add the flag check to your code
Use the OpenFeature SDK to evaluate the flag in your application:
import { OpenFeature } from '@openfeature/server-sdk';
const client = OpenFeature.getClient();
app.get('/checkout', async (req, res) => {
const useNewCheckout = await client.getBooleanValue(
'checkout-redesign',
false,
{ targetingKey: req.user.id }
);
if (useNewCheckout) {
return res.render('checkout-v2');
}
return res.render('checkout');
});
from openfeature import api
client = api.get_client()
@app.route('/checkout')
def checkout():
use_new = client.get_boolean_value(
'checkout-redesign',
False,
EvaluationContext(targeting_key=current_user.id),
)
if use_new:
return render_template('checkout_v2.html')
return render_template('checkout.html')
Step 3: Start with internal users
Before using percentage rollouts, enable the flag for your team using targeting rules. In Flipswitch, add a rule that matches your team’s email domain or specific user IDs.
This gives you a production smoke test with real data and real traffic, but only for people who know what to expect.
Step 4: Roll out gradually
Once the internal test looks good, switch to percentage-based rollout:
| Stage | Percentage | Duration | What to monitor |
|---|---|---|---|
| Canary | 1% | 1-2 hours | Error rates, latency |
| Early adopters | 5% | 1 day | Conversion metrics, user feedback |
| Wider release | 25% | 2-3 days | Business KPIs, support tickets |
| Majority | 75% | 1 week | Edge cases, performance at scale |
| Full release | 100% | - | Confirm stability, plan flag removal |
Step 5: Monitor at each stage
At each stage, check:
- Error rates: Are errors higher for users with the new feature?
- Latency: Is the new code path slower?
- Business metrics: Conversion rate, revenue, engagement. Whatever matters for this feature
- Support tickets: Are users reporting issues?
If anything looks off, pause the rollout. If it’s bad, roll back to 0%.
Step 6: Roll back if needed
Rolling back is the whole point of gradual rollouts. In Flipswitch, set the rollout percentage to 0% and the change propagates to all connected SDKs in milliseconds via SSE.
No deploy. No hotfix. No downtime.
The flag check in your code keeps evaluating, it just returns false for everyone now.
Step 7: Clean up after full rollout
Once the feature is at 100% and has been stable for your confidence period (we recommend at least 1-2 weeks), it’s time to clean up:
- Remove the flag check from your code, make the new behavior the default
- Remove the old code path
- Deploy the cleanup
- Archive the flag in Flipswitch
This keeps your codebase clean and prevents flag accumulation.
Common mistakes to avoid
Skipping the canary stage. Going from 0% to 25% means your first exposure is to a quarter of your users. Start at 1%.
Not monitoring between stages. Increasing the percentage on a schedule regardless of metrics defeats the purpose. Each stage should be a deliberate decision.
Forgetting to clean up. A flag at 100% for 6 months is tech debt. Schedule the cleanup as part of the rollout plan.
Rolling out during low-traffic periods. If you roll out at 2am on a Sunday, you won’t have enough traffic to detect issues. Roll out during normal business hours when you can react.
Wrapping up
Gradual rollouts are the safest way to ship new features. Deploy the code behind a flag, test with your team, then ramp up the percentage while monitoring every step. If anything goes wrong, roll back instantly.
The total investment is a few extra lines of code and a few minutes configuring the rollout in your dashboard. The payoff is sleeping soundly after every release.
Get started with Flipswitch and ship your first gradual rollout today.