A guardrail watches a metric against a rollout in progress and acts on it without a human deciding in the moment. This tutorial attaches one that aborts a rollout if its error rate goes above 5%, then walks through how to see what it decided and why.
1. Attach a guardrail to a scheduled or active rollout
POST /v1/rollouts/{rollout_id}/guardrails requires the rollout to be scheduled or active (it's rejected once the rollout has completed or aborted), and the referenced metric definition to belong to the same project as the rollout's flag config:
const res = await fetch(
`https://api.rollfuse.com/v1/rollouts/${rolloutId}/guardrails`,
{
method: "POST",
headers: {
Authorization: `Bearer ${token}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
metric_definition_id: errorRateMetricId,
comparison_operator: "gt",
threshold: 0.05,
evaluation_window_seconds: 300,
}),
}
);
const guardrail = await res.json();
console.log(guardrail.id, guardrail.comparison_operator, guardrail.threshold);
comparison_operator is one of gt, gte, lt, lte. This guardrail reads: every 300-second window, if the error rate metric is greater than 0.05, act on it. evaluation_window_seconds controls how much data each check looks at, so a spike shorter than the window won't necessarily trigger it on its own.
2. What the guardrail does automatically
Once attached, the guardrail is evaluated on a recurring basis against fresh observations for its metric, with no further action from you. Depending on what it observes, it can produce one of these outcomes on the rollout: rollout_aborted, rollout_paused, rollout_resumed, or rollout_promoted (advancing past a healthy stage), alongside none when nothing changed. A breach past the threshold is what triggers rollout_aborted or rollout_paused, not something you call manually; you can still call POST /v1/rollouts/{rollout_id}/abort or .../pause yourself if you want to act before the guardrail would.
You can list every guardrail on a rollout with GET /v1/rollouts/{rollout_id}/guardrails, and fetch one by id with GET /v1/rollouts/{rollout_id}/guardrails/{guardrail_id}.
3. Read the guardrail's evaluation history
Every check the guardrail performs is recorded as a PolicyEvaluation. List them with GET /v1/rollouts/{rollout_id}/guardrails/{guardrail_id}/policy-evaluations, ordered oldest first:
const historyRes = await fetch(
`https://api.rollfuse.com/v1/rollouts/${rolloutId}/guardrails/${guardrail.id}/policy-evaluations`,
{ headers: { Authorization: `Bearer ${token}` } }
);
const { policy_evaluations } = await historyRes.json();
for (const evaluation of policy_evaluations) {
console.log(
evaluation.evaluated_at,
evaluation.observed_value,
evaluation.breached,
evaluation.action, // "none" | "rollout_aborted" | "rollout_paused" | "rollout_resumed" | "rollout_promoted"
evaluation.reason
);
}
observed_value is the metric's value for that window, breached tells you whether it crossed threshold, and reason explains edge cases in plain language, for example insufficient data in the window, or a sibling guardrail on the same rollout already having aborted it in that tick.
Where to go next
A guardrail only sees data for the rollout it's attached to; if you haven't scheduled the rollout yet, start with the percentage rollout tutorial, and attach the guardrail before, or right after, the rollout's first stage goes live.