---
title: "Control execution with action policies"
description: "Target handlers and stages with retry, timeout, rate-limit, and circuit-breaker rules, and inspect effective behavior."
category: "Operate Pipelogiq"
---

Action policies apply execution rules to matching stages. They are an experimental surface: runtime enforcement exists, but the configuration schema contains options that are not complete guarantees. Start with explicit stage retry/timeout options, then introduce policies when several workflows need a shared rule.

Administrators manage policies under **Action Policies**. Operators can inspect run behavior but do not manage this page. Policy administration is distinct from the overlap/catch-up settings on a schedule.

## Choose the rule

| Type | Purpose | Runtime result |
| --- | --- | --- |
| `retry` | Retry selected reported failures. | Schedules a new attempt when the winning rule allows it. |
| `timeout` | Limit stage execution time. | Uses the strictest applicable step timeout. |
| `rate_limit` | Limit dispatch based on recent started stages. | Places a stage in Throttled until eligible again. |
| `circuit_breaker` | Block dispatch after observed handler failures. | Can fail the stage and pipeline when the breaker is open. |

Circuit blocking is not simply a paused job that will automatically resume after a cooldown. Inspect the run and choose recovery deliberately.

## Create a narrowly targeted policy

1. Open **Action Policies** and create a policy.
2. Give it a recognizable name and description explaining the protected dependency.
3. Choose its type and environment.
4. Target a specific handler/stage or a small set of pipelines/labels.
5. Preview the matched scope before activating it.
6. Run a controlled test and inspect the effective policies for the affected stage.

Do not begin with a global rule unless it is intended to affect all matching work. Status values are `active`, `paused`, and `disabled`; orphaned inline policies can also appear in lists.

## JSON shape

Policy JSON uses singular `rule`, and target fields are `pipelines`, `stages`, `handlers`, `tagsInclude`, and `tagsExclude`. This is a retry policy body; SDKs can also include policy definitions in pipeline/stage creation:

```json
{
  "name": "retry-email-transport",
  "description": "Retry transient email-provider failures.",
  "type": "retry",
  "status": "active",
  "environment": "all",
  "targeting": {
    "pipelines": [],
    "stages": [],
    "handlers": ["EmailInvoiceHandler"],
    "tagsInclude": [],
    "tagsExclude": []
  },
  "rule": {
    "maxAttempts": 3,
    "backoff": "exponential",
    "baseDelayMs": 1000,
    "maxDelayMs": 30000,
    "jitter": true,
    "retryOn": { "errorCodes": ["UPSTREAM_ERROR", "TRANSPORT_UNAVAILABLE"] }
  }
}
```

Policy delays/timeouts use milliseconds where the field says `Ms`. Stage retry options use seconds. Confusing the units can turn a useful timeout into immediate failures.

`maxAttempts` is currently compared to the stored automatic retry count; do not interpret its label as a promise of exactly that many total handler executions. Delivery recovery and manual reruns are additional reasons an execution attempt can occur. Use business idempotency independently of retry limits.

## Targeting and precedence

Pipeline targets are pipeline IDs represented as strings. Stage and handler targets match names case-insensitively; they are not glob patterns. Included tags must match, and an excluded tag prevents a match. Environment is one of `all`, `prod`, `staging`, or `dev`; make your workflow metadata and policy environment agree.

For matching rules:

- **Timeout:** the lowest applicable step timeout wins, including the stage's own timeout.
- **Retry:** the highest-precedence matching retry rule wins. The effective response explains selection and shadowing.
- **Rate limits:** matching rules remain active together; any exceeded rule can throttle.
- **Circuit breakers:** matching rules remain active together; any open breaker can block.

An effective retry policy takes precedence over stage retry settings. If its error filter does not match, the engine does not retry using the stage fallback. Terminal error classifications and `retryable:false` still prevent automatic retry.

## Rate limit scope

The `keyBy` values are `global`, `tenant`, `user`, and `custom`. Current runtime meanings are:

| Key | Grouping |
| --- | --- |
| `global` | Recent started stages across the store. |
| `tenant` | Application scope. |
| `user` | Pipeline scope; it is not a dashboard user's identity. |
| `custom` | Handler name. |

`limit`, `windowSeconds`, and optional `burst` determine the dispatch threshold. These rules operate on workflow dispatch observations. They are not a replacement for a shared external API quota service or a strict distributed rate limiter under every concurrency pattern.

## Inspect unexpected behavior

For a throttled, timed-out, or unexpectedly terminal run, ask an administrator to inspect the effective policy resolution for the stage. The internal route is `GET /api/policies/effective/stages/{stageId}` through the dashboard proxy and requires an administrator session. It explains matched, selected, shadowed, and ignored rules.

Compare the handler name, environment, included/excluded tags, stage options, and the result's error code. Temporarily pausing a policy changes future evaluations; it does not automatically reconstruct work that already failed.

## Current limits

Use `retryOn.errorCodes`; the schema's `retryOn.httpStatus` is not an enforced HTTP response filter in this runtime. Use `timeout` with `appliesTo:"step"`; broader timeout scopes are not implemented as pipeline deadlines. `halfOpenMaxCalls` is not a complete half-open circuit-breaker guarantee.

Policy data is persisted in PostgreSQL. API policy-management views maintain a local index loaded at startup, while execution reads database policy data. Do not assume instantaneous coherent policy-management views across several API replicas. Validate policy changes on the actual deployment before extending a single-instance operating model.
