> For the complete documentation index, see [llms.txt](https://docs.openiam.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.openiam.com/administration-guide/pbac/roll-out-a-policy.md).

# Roll a policy out safely

Take a policy from draft to fully enforced through shadow and partial modes, understand how deterministic bucketing decides who is governed, and know what the audit trail records at each stage.

## What this is, and when you need it

A wrong access-control policy locks real users out of real systems, and unlike a wrong entitlement it does so for everyone it matches at once. Enforcement modes exist so that activating a policy and enforcing it are two different decisions.

Read this before setting any policy to `ACTIVE`.

{% hint style="danger" %}
**A policy with no enforcement mode recorded is enforced.** The mode only *adds* staging on the way to full enforcement — it is not a safe default that you opt out of. An `ACTIVE` policy with the **Mode** column showing a dash governs every request it matches, immediately, exactly as if it were `FULL`.

If you take one thing from this page: set the mode **before** you set the status.
{% endhint %}

## At a glance

|                          |                                                                                                                                                                                                |
| ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **You will end up with** | A policy enforced against live traffic, having first been observed and then narrowed to a cohort                                                                                               |
| **Where**                | **Administration → PBAC Policies** → the policy's **Enforcement mode**                                                                                                                         |
| **You need first**       | A `DRAFT` that [simulates](/administration-guide/pbac/simulate-a-policy.md) correctly, and somewhere to watch divergences — [Trace a decision](/administration-guide/pbac/trace-a-decision.md) |
| **Takes**                | Minutes to change a mode; days to weeks to walk the path properly                                                                                                                              |
| **Reversible**           | Yes — narrowing or deprecating takes effect on the next cache sweep. What a policy already denied stays denied                                                                                 |

## Before you begin

The mode is only meaningful while the status is `ACTIVE`. A `DRAFT` is never evaluated, whatever mode is set on it — so setting the mode first, then the status, is safe in the order it sounds risky.

Changes take effect on a **cache sweep, not immediately**: with default settings a status or mode change is live on every node within about six minutes. Plan around that when you widen or pull back — see [PBAC reference](/administration-guide/pbac/pbac-reference.md#caching-and-propagation).

## The three modes

| Mode      | What happens                                                                                                                                                                                                                                                                                                                    |
| --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `SHADOW`  | The policy is evaluated on every request it matches and each outcome is recorded, but **the decision served is the one the enforced policies reached** — as though this policy were not active. Where the shadow outcome disagrees with what was served, the divergence is logged. That divergence count is the number to watch |
| `PARTIAL` | Enforced for a percentage of users, skipped entirely for the rest. Membership is **deterministic**, not sampled per request                                                                                                                                                                                                     |
| `FULL`    | Enforced against every request it matches                                                                                                                                                                                                                                                                                       |

The mode is read on the decision path every time the policy is applicable, so moving between stages needs no redeployment.

## How partial rollout picks its cohort

Selecting `PARTIAL` reveals **Rollout percentage** (0–100). Each user is hashed into one of 100 buckets **per policy**, and the policy governs the users whose bucket falls below the percentage. That gives three properties worth relying on:

* **Stable.** The same user gets the same answer for the same policy on every node and across restarts. Nobody flickers in and out of enforcement between two clicks.
* **Independent cohorts.** Two policies at 10% do not both land on the same tenth of the directory.
* **Monotonic widening.** Raising 10% to 20% keeps everyone already governed and only adds users. Nobody who was enforced drops back out.

Users outside the rollout are not evaluated against the policy at all — for them it is as if it were not active.

{% hint style="warning" %}
**A `PARTIAL` policy with no percentage set governs nobody.** It is not a synonym for a small rollout, and it is not an error either — an unnarrowed `PARTIAL` would simply be `FULL`, so the field starts empty and waits for you. A policy sitting at `PARTIAL` with nothing entered is doing nothing at all, which looks identical to a policy that is working and matching no one.
{% endhint %}

## The path

{% stepper %}
{% step %}

### Iterate as a draft until it decides correctly

Author it, and [simulate](/administration-guide/pbac/simulate-a-policy.md) against real users and resources until known cases come out right. Nothing here touches live access.
{% endstep %}

{% step %}

### Activate in shadow, and watch the divergences

Set the mode to `SHADOW` **first**, then the status to `ACTIVE`. The policy now sees production traffic and decides on it, while the decision served to callers is unchanged.

Review the divergence entries in [the decision log](/administration-guide/pbac/trace-a-decision.md). A divergence is the policy disagreeing with what was actually served — which is precisely the set of requests whose outcome would change if you enforced. Read them before you do.
{% endstep %}

{% step %}

### Move to partial at a small percentage

`PARTIAL` at something like 10%. Because widening is monotonic, this cohort stays governed as you raise the number — you are only ever adding people, never swapping which ones are affected.

Widen gradually, and let a sweep pass between steps so you are reading the effect of the last change rather than the one before it.
{% endstep %}

{% step %}

### Move to full

`FULL` enforces against every matching request.
{% endstep %}

{% step %}

### Retire it by deprecating, not deleting

Set the status to `DEPRECATED` when the policy has served its purpose. It stops being loaded by the engine and stays readable.

Deleting removes the header and every version irreversibly — see [Roll it back](/administration-guide/pbac/create-a-policy.md#roll-it-back). Deprecate unless you have a reason to destroy the history.
{% endstep %}
{% endstepper %}

## Verification

| What to check                    | How                                                                                                                                           |
| -------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| The mode is actually recorded    | The **Mode** column in the library shows `SHADOW`, `FULL`, or `PARTIAL` with a percentage. **A dash means no mode — the policy is enforcing** |
| Shadow is observing, not serving | Decisions served to callers are unchanged, while decision entries record the policy as *observed*                                             |
| The rollout cohort is stable     | The same test user gets the same answer across repeated requests and across nodes                                                             |
| A change has propagated          | Allow write sweep + read sweep — about six minutes with defaults — then re-test                                                               |
| What the policy actually did     | Each decision entry records, per policy, whether it applied, observed or was skipped, and the mode in force at the time                       |

## When it goes wrong

| Symptom                                                | Cause                                                                | Fix                                                                                                       |
| ------------------------------------------------------ | -------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- |
| A policy started enforcing the moment it was activated | No mode was recorded, and an `ACTIVE` policy without one is enforced | Set the mode, then re-activate. This is the failure this page exists to prevent                           |
| A `PARTIAL` policy affects nobody                      | No rollout percentage is set, so it governs nobody                   | Enter a percentage                                                                                        |
| A mode change appears to do nothing                    | Cache sweep has not completed                                        | Wait out write sweep + read sweep, about six minutes with defaults                                        |
| A `DRAFT` with a mode set is not evaluated             | Expected. The mode only applies while the status is `ACTIVE`         | Activate it when you are ready                                                                            |
| Users appear to move in and out of a partial rollout   | They should not — bucketing is deterministic per policy              | Confirm you are testing one policy; two policies at the same percentage cover different cohorts by design |
| Shadow rollout moved the numbers in a report           | It should not — the indexed decision is always the one served        | Shadow outcomes are recorded as informational lines only. If a report moved, something else changed       |

## What the audit trail records

Every decision entry records, **per policy**, how it participated — applied, observed, or skipped as outside a partial rollout — together with the mode in force at decision time. A `PARTIAL` policy is recorded with its percentage, as `policy-1=PARTIAL@25`.

That detail matters because a policy ramps through modes over its life. An entry naming only the outcome would stop being interpretable the moment the policy moved on; recording the mode makes an old decision still readable a year later.

Shadow outcomes are informational lines only. The indexed decision is always the one actually served, so a shadow rollout cannot move the numbers your reports read.

## Related

* [Simulate a policy](/administration-guide/pbac/simulate-a-policy.md) — the step before this one
* [Trace a decision](/administration-guide/pbac/trace-a-decision.md) — where divergences and participation are read
* [The policy model](/administration-guide/pbac/policy-model.md) — status, mode and version, and how they interact
* [PBAC reference](/administration-guide/pbac/pbac-reference.md#caching-and-propagation) — the sweep intervals behind the six minutes

*Applies to OpenIAM 2026.8.1. Last reviewed 13 August 2026.*


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.openiam.com/administration-guide/pbac/roll-out-a-policy.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
