ShipOS docs
Rollouts Stable ramp

Percentage Rollouts

A rollout serves the on value to a share of your users and the off value to the rest. Bucketing is deterministic and stable, so ramping up is safe , you only ever add users, never reshuffle the ones already in.

Stable bucketing

Each user is assigned a bucket by hashing the flag key together with the userId. The same user always lands in the same bucket for a given flag, so:

  • Raising rolloutPct from 10 to 25 keeps every user who was already in and adds a new slice, nobody flips out.
  • A user's experience is consistent across page loads, devices, and sessions.
  • The rollout is independent per flag, being in one flag's 10% tells you nothing about another's.

Anonymous users

No userId, no bucket

Percentage gating needs a stable identity. Evaluations without a userId can't be bucketed, so they fall to the off/base value for any percentage gate. Pass a userId, even a stable anonymous/device id, if you want anonymous traffic in a rollout.

A ramp sequence

A typical prod ramp. Watch metrics between each step; because bucketing is stable you can pause at any percentage or roll back without churning who's already in.

SteprolloutPctWhat it means
Canary1Smoke-test on real traffic
Early10Enough volume to read metrics
Half50A/B the old vs. new path
Full100Everyone on the new path

Setting a rollout

Set the percentage via the MCP tool or the config API.

text
Claude → set_rollout { key: "checkout-v2", env: "prod", percent: 10 }
  ✅ checkout-v2 @ prod → 10% rollout
http
PUT https://app.shipos.app/api/v1/flags/{id}/environments/prod/config
Authorization: Bearer sos_agt_...
Content-Type: application/json

{
  "expectedVersion": 8,
  "rolloutPct": 10
}

Ramps apply immediately, and reverse just as fast

Any valid key (agent or admin) applies a rollout change directly; every change is audited by actor. If a ramp misbehaves, drop the percentage back or hit the flag's kill switch, both take effect in seconds.

How it composes

A rollout is the base gate: it applies when no targeting rule matched a user. A rule can also carry its own rolloutPct to ramp within a matched cohort. See how a value is chosen.