# Run a controlled rollout

Move a change from safe defaults to a completed release with an explicit rollback path.

A rollout is an operating process around a flag, not merely a percentage rule. Define the final state,
observation signals, decision owner, and rollback condition before production changes begin.

Use this workflow for temporary release flags. Long-lived configuration and operational controls need
different ownership and do not necessarily end in code removal.

<FlowDiagram
  ariaLabel="Controlled rollout"
  items={[
    "Safe fallback",
    "Non-production validation",
    "Internal cohort",
    "Percentage expansion",
    "Final fallback",
    "Code cleanup",
  ]}
/>

## Define the release contract

Before creating the production rule, record:

- The flag owner and application owner.
- The existing safe behaviour.
- The intended final behaviour.
- The rollout unit, such as `account.id`.
- Health and business signals to observe.
- The observation window for each step.
- The condition that pauses or rolls back.
- The deployment that removes the old branch.

Create a temporary release flag with a cleanup date. Use a durable key and the smallest suitable type.

## Prepare safe defaults

Configure each required environment explicitly. Development can default to the new behaviour while
production remains on the known-safe existing behaviour.

Give every caller a safe typed default. Confirm that missing configuration, startup failure, and
hosted timeout do not produce a dangerous application state.

Do not start production rollout until the flag type, environment binding, key scope, and context
contract have been verified in non-production.

## Validate outside production

Exercise both application branches in development and staging. Test matching, non-matching, and
missing context. For a percentage rollout, use fixed identifiers to confirm stable assignment.

Validate more than rendering. Check data writes, downstream calls, retries, caching, permissions,
performance, and rollback compatibility where the guarded branch affects them.

## Target an internal cohort

Add a narrow internal or approved cohort before a percentage. Place it before broad plan and rollout
rules so it cannot be shadowed.

Example production model:

1. `account.id in [internal_account]` returns `true`.
2. Pro accounts enter a percentage by `account.id`.
3. The environment fallback remains `false`.

Verify the internal cohort through the application's own observability. FeatureGate request counts do
not prove that every local SDK branch executed successfully.

## Expand the percentage

Choose a schedule appropriate to risk. A common sequence is 5%, 10%, 25%, 50%, and 100%, but no
sequence is universally safe.

At each step:

1. Confirm the previous observation window completed.
2. Review application health and outcome telemetry.
3. Review hosted errors, rate limits, and direct request volume.
4. Add a change note with the decision and rollback condition.
5. Increase the existing rule without changing its rollout path.

Do not change identifier normalization during rollout. Moving from `user.id` to `account.id` creates a
new cohort assignment and should be treated as a new release step.

## Pause or roll back

Pause by leaving allocation unchanged while investigation continues. A pause preserves cohort
assignment and avoids introducing another variable.

Roll back by reducing or removing the production rule so evaluation returns the known-safe fallback.
Verify both hosted configuration and application behaviour after the change.

Use a kill switch only when a prepared emergency override is clearer and faster than ordinary rule
changes. Do not improvise a kill switch for every normal rollout reversal.

> [!WARNING] Configuration is not instant everywhere
> Hosted evaluation sees current configuration. Snapshot clients observe a
> change after a successful refresh and can retain an older snapshot during
> failure.

## Complete the release

When the new behaviour is the intended default:

1. Change the production fallback to the new value.
2. Remove percentage and temporary cohort rules.
3. Observe the stable fallback-only state.
4. Remove the old application branch and obsolete tests.
5. Deploy and verify the unguarded behaviour.
6. Remove unused context fields and wrappers.
7. Archive the flag after required callers stop depending on it.

A 100% rule is not completion. It leaves targeting complexity, guarded code, and a runtime dependency.

## What to record

Use change notes for reason, owner, observation window, outcome, and rollback decision. Never include
raw customer identifiers, secrets, full context, targeting values, or sensitive incident payloads.

Related pages: [Percentage rollouts](/docs/flags/percentage-rollouts),
[Project insights](/docs/operate/project-insights), and
[Review and clean up flags](/docs/operate/review-and-clean-up-flags).
