Use Cases

Gradual Rollouts

Gradually release features from 0% to 100%

A gradual rollout releases a feature to a growing portion of users over time. Start at 0%, increase gradually, reach 100%.

How It Works

When you set a gradual rollout:

10% -> new-feature
90% -> old-feature

Flipswitch:

  1. Hashes the user's targetingKey
  2. Maps the hash to a bucket (0-99)
  3. Returns the variant based on bucket

User alice@example.com might hash to bucket 42. With 10% rollout, she gets the old feature. Increase to 50%, and she gets the new feature.

Properties

Deterministic. Same user, same bucket, same variant. Alice always sees the same thing.

Consistent. Increasing from 10% to 20% doesn't reassign users in the first 10%. Users who had the new feature keep it.

Even distribution. Hash function distributes users evenly across buckets. 10% means roughly 10% of users, not exactly.

Implementation

1. Create the Flag

Key: new-pricing-page
Type: Boolean
Default: false (old page)

2. Configure Rollout

Start at 0%:

0% -> true (new page)
100% -> false (old page)

3. Evaluate in Code

const showNewPricing = await client.getBooleanValue('new-pricing-page', false, {
  targetingKey: userId
});
 
return showNewPricing ? <NewPricingPage /> : <OldPricingPage />;

4. Increase Gradually

Day 1:  1% -> true
Day 3:  5% -> true
Day 5:  10% -> true
Day 7:  25% -> true
Day 10: 50% -> true
Day 14: 100% -> true

Watch metrics at each stage before increasing.

The targetingKey

The targeting key determines which bucket a user falls into:

// Good: consistent per user
await client.getBooleanValue('feature', false, {
  targetingKey: user.id  // User always sees same variant
});
 
// Good: consistent per session (for anonymous users)
await client.getBooleanValue('feature', false, {
  targetingKey: sessionId
});
 
// Bad: inconsistent
await client.getBooleanValue('feature', false, {
  targetingKey: Math.random().toString()  // Different every time!
});

For stateless services, use a consistent identifier like request ID:

// Server-side with request correlation
await client.getBooleanValue('feature', false, {
  targetingKey: request.headers['x-request-id']
});

Combining with Rules

Targeting rules are evaluated before gradual rollouts. If a rule matches, the rollout is skipped:

Targeting Rules:
  Rule 1: IF user in segment "internal" THEN return "enabled"
  Rule 2: IF user in segment "beta" THEN return "enabled"

Gradual Rollout (for everyone else):
  10% -> enabled
  90% -> disabled

Internal and beta users always get the new feature (via rules). Everyone else has a 10% chance (via rollout).

Multi-Variant Rollouts

For A/B tests or multiple variants:

Type: String
Variants: control, treatment-a, treatment-b

Rollout:
40% -> control
30% -> treatment-a
30% -> treatment-b
const variant = await client.getStringValue('checkout-experiment', 'control', {
  targetingKey: userId
});

Ring-Based Rollouts

Some teams use "rings" for staged rollouts:

Ring 0: Internal employees (segment rule)
Ring 1: 1% of production
Ring 2: 10% of production
Ring 3: 50% of production
Ring 4: 100% of production

This combines segments (for ring 0) with gradual rollouts (for rings 1-4).

Rollback

If something goes wrong at 25%:

Before: 25% -> new-feature
After:  0% -> new-feature

All users immediately get the old behavior. Users who had the new feature switch to the old one.

Cleanup

At 100% with stable metrics:

  1. Remove the flag check from code
  2. Keep the flag for a week (in case you need to roll back)
  3. Delete the flag
  4. Remove the old code path
// Before
if (showNewPricing) {
  return <NewPricingPage />;
} else {
  return <OldPricingPage />;
}
 
// After cleanup
return <NewPricingPage />;

On this page