Gradual rollouts
Gradual rollouts let you release features to a subset of users and increase exposure over time. Use them to:
- Reduce risk when launching new features
- Test performance under increasing load
- Gather feedback before full release
- Roll back instantly if issues arise
How percentage rollouts work
Replane uses deterministic bucketing:
- Hash the bucketing key (e.g.,
userId) with the config name - Convert hash to a number 0-99
- Compare against the percentage threshold
User A: hash("feature-x" + "user-a") / MAX_HASH_VALUE * 100 = 23
User B: hash("feature-x" + "user-b") / MAX_HASH_VALUE * 100 = 67
User C: hash("feature-x" + "user-c") / MAX_HASH_VALUE * 100 = 45
At 30% rollout:
- User A (23): ✓ Enabled
- User B (67): ✗ Disabled
- User C (45): ✗ Disabled
At 50% rollout:
- User A (23): ✓ Enabled
- User B (67): ✗ Disabled
- User C (45): ✓ Enabled (now included)
Key properties:
- Deterministic: Same user always gets same result
- Consistent: Users enabled at 10% stay enabled at 20%
- Client-side: No server round-trip needed
Create a percentage rollout
- Create a feature flag config with
falseas base value - Add an override:
- Condition:
10%ofuserId - Value:
true
- Condition:
- Save
Read with context
const enabled = replane.get('feature-new-checkout', {
context: { userId: user.id }
});
if (enabled) {
showNewCheckout();
} else {
showOldCheckout();
}
Increase the rollout
Edit the override and change the percentage:
10% → 25% → 50% → 75% → 100%
Users previously included stay included as you increase.
Rollout strategies
Linear increase
Simple incremental rollout:
Day 1: 5%
Day 2: 10%
Day 3: 25%
Day 4: 50%
Day 5: 75%
Day 6: 100%
Staged rollout
Pause at key milestones to validate:
Stage 1: 1% - Verify basic functionality
Stage 2: 10% - Monitor error rates
Stage 3: 50% - Check performance under load
Stage 4: 100% - Full release
Ring-based rollout
Target different groups in sequence:
Config: feature-new-editor
Base value: false
Override 1: Internal team
Condition: email endsWith "@company.com"
Value: true
Override 2: Beta users
Condition: userGroup equals "beta"
Value: true
Override 3: 10% rollout
Condition: 10% of userId
Value: true
Internal team tests first, then beta users, then gradual public rollout.
Bucketing keys
User ID (most common)
Each user gets consistent experience:
replane.get('feature', { context: { userId: user.id } });
Session ID
Per-session randomization (user might see different values across sessions):
replane.get('feature', { context: { sessionId: session.id } });
Organization ID
All users in same org get same experience:
replane.get('feature', { context: { orgId: user.organizationId } });
Device ID
Consistent across anonymous users on same device:
replane.get('feature', { context: { deviceId: getDeviceId() } });
Combining conditions
Target specific segments with percentage:
Override: 20% of premium users
Conditions:
- plan equals "premium"
- 20% of userId
Value: true
// Only premium users are considered for the rollout
replane.get('feature', {
context: { userId: user.id, plan: user.plan }
});
Monitoring rollouts
Track metrics by variant
const variant = replane.get('checkout-flow', {
context: { userId: user.id }
});
analytics.track('checkout_started', {
variant,
userId: user.id
});
Compare performance
Monitor key metrics for each group:
- Error rates
- Latency
- Conversion rates
- User engagement
Set up alerts
Alert on metric differences between control and treatment groups.
Rollback
If issues arise, reduce the percentage or set base value:
Option 1: Reduce percentage
50% → 10% → 0%
Option 2: Disable override
- Delete or disable the percentage override
- All users get base value (
false)
Option 3: Use version history
- Click on version history
- Restore a previous version
Changes propagate instantly via SSE.
A/B testing
For true A/B tests with multiple variants:
Config: experiment-checkout
Base value: "control"
Override: Treatment A
Condition: userId in bucket 0-33%
Value: "treatment-a"
Override: Treatment B
Condition: userId in bucket 34-66%
Value: "treatment-b"
const variant = replane.get('experiment-checkout', {
context: { userId: user.id }
});
switch (variant) {
case 'treatment-a':
showCheckoutVariantA();
break;
case 'treatment-b':
showCheckoutVariantB();
break;
default:
showControlCheckout();
}
Best practices
Start small
Begin with 1-5% to catch issues early:
1% → 5% → 10% → 25% → 50% → 100%
Monitor between stages
Wait and observe metrics before increasing:
- At least 1 hour for quick validation
- 24-48 hours for meaningful data
Document your rollout
Note the plan and current stage:
Config description:
Rollout plan: 5% (Mon) → 25% (Wed) → 50% (Fri) → 100% (Mon)
Current: 25% since 2024-01-15
Have a rollback plan
Before starting:
- Know how to roll back
- Define rollback triggers (error rate > 1%, latency > 500ms)
- Test rollback in staging
Clean up after full rollout
Once at 100% for a week with no issues:
- Remove the override
- Change base value to
true - Consider removing the feature flag from code
Next steps
- Feature Flags — Toggle features
- Override Rules — Advanced targeting
- JavaScript SDK — Full API reference