Policies
Reference for the declarative manifests that define Catalyst policies. For the conceptual story see Policies. For end-to-end usage see Resiliency and App IDs.
Policies are applied with the diagrid CLI. The target project is provided by the --project flag, not by a field in the manifest:
diagrid resiliency create -f resiliency.yaml --project my-project
diagrid configuration create -f configuration.yaml --project my-project
Manifest envelope
Every policy manifest shares the same top-level shape:
apiVersion: dapr.io/v1alpha1
kind: <Resiliency | Configuration>
metadata:
name: <policy-name>
scopes:
- <app-id-1>
- <app-id-2>
spec:
# ...kind-specific spec below
| Field | Type | Required | Description |
|---|---|---|---|
apiVersion | string | yes | Must be dapr.io/v1alpha1. |
kind | string | yes | Resiliency or Configuration. |
metadata.name | string | yes | Unique policy name within the project. |
scopes | string[] | no | App IDs the policy applies to. Top-level (sibling of spec). Omit to leave the policy unbound. |
Resiliency policy
A resiliency policy defines named retry, timeout, and circuit-breaker behaviours, then binds them to outbound calls by target.
Spec
spec:
policies:
timeouts:
<policy-name>: <duration>
retries:
<policy-name>:
policy: constant | exponential
duration: <duration>
maxInterval: <duration> # exponential only
maxRetries: <int> # -1 for unlimited
matching:
httpStatusCodes: "<comma-separated codes or ranges>"
gRPCStatusCodes: "<comma-separated codes>"
circuitBreakers:
<policy-name>:
maxRequests: <int>
interval: <duration>
timeout: <duration>
trip: "<CEL expression>"
targets:
apps:
<app-id>:
timeout: <timeout-policy-name>
retry: <retry-policy-name>
circuitBreaker: <circuit-breaker-policy-name>
circuitBreakerCacheSize: <int>
components:
<component-name>:
inbound:
timeout: <timeout-policy-name>
retry: <retry-policy-name>
circuitBreaker: <circuit-breaker-policy-name>
outbound:
timeout: <timeout-policy-name>
retry: <retry-policy-name>
circuitBreaker: <circuit-breaker-policy-name>
Retry policy fields
| Field | Type | Description |
|---|---|---|
policy | constant | exponential | Backoff shape. Constant waits duration between attempts; exponential grows the wait up to maxInterval. |
duration | duration string (e.g. 5s) | Wait between attempts (constant) or initial wait (exponential). |
maxInterval | duration string | Upper bound on the wait for exponential policies. Ignored for constant. |
maxRetries | int | Maximum attempts after the initial call. -1 means retry indefinitely. |
matching.httpStatusCodes | string | Comma-separated HTTP codes or ranges to retry, e.g. "500,501,502,503,504". Unmatched codes fail immediately. |
matching.gRPCStatusCodes | string | Comma-separated gRPC status codes to retry, e.g. "14,4,8". |
Circuit-breaker fields
| Field | Type | Description |
|---|---|---|
maxRequests | int | Number of probe requests permitted while the breaker is half-open. |
interval | duration string | Sliding window over which failures are counted. |
timeout | duration string | Time the breaker stays open before transitioning to half-open. |
trip | CEL expression | Trip condition. Evaluated against the variables below, e.g. "consecutiveFailures > 5". |
The trip expression is evaluated as CEL with the following variables in scope:
| Variable | Description |
|---|---|
requests | Total requests observed in the current window. |
consecutiveFailures | Consecutive failures since the last success. |
consecutiveSuccesses | Consecutive successes since the last failure. |
totalFailures | Total failures in the current window. |
totalSuccesses | Total successes in the current window. |
Target fields
apps.<app-id> binds policies to outbound service invocations to that App ID. components.<component-name>.outbound binds policies to calls out to the component; inbound binds policies to deliveries from the component (for example pub/sub message delivery into the app).
Each target slot accepts the name of a policy defined in policies.timeouts, policies.retries, or policies.circuitBreakers. Bindings are optional; omit a slot to leave that dimension unbounded for the target.
circuitBreakerCacheSize (apps only) caps the number of per-instance breakers cached for that target.
Defaults
If you omit a dimension, Catalyst applies these defaults at the data plane:
| Dimension | Default value |
|---|---|
| Timeout | 10s |
| Retry | constant, 5s between attempts, 5 retries, matching HTTP 500,501,502,503,504 and gRPC 14,4,8 |
| Circuit breaker | maxRequests: 1, interval: 5s, timeout: 20s, trip: consecutiveFailures > 5 |
Worked example
apiVersion: dapr.io/v1alpha1
kind: Resiliency
metadata:
name: order-service-resiliency
scopes:
- order-service
spec:
policies:
timeouts:
fastCall: 2s
retries:
transientRetry:
policy: exponential
duration: 200ms
maxInterval: 5s
maxRetries: 4
matching:
httpStatusCodes: "503,504"
gRPCStatusCodes: "14"
circuitBreakers:
defaultBreaker:
maxRequests: 1
interval: 30s
timeout: 60s
trip: "consecutiveFailures > 5"
targets:
apps:
inventory-service:
timeout: fastCall
retry: transientRetry
circuitBreaker: defaultBreaker
components:
orders-statestore:
outbound:
timeout: fastCall
retry: transientRetry
circuitBreaker: defaultBreaker
Configuration
A configuration sets App ID-level runtime behaviour: access control lists, HTTP pipelines, distributed tracing (private regions only), and workflow runtime parameters.
Spec
spec:
accessControl:
defaultAction: allow | deny
trustDomain: <trust-domain>
policies:
- appId: <caller-app-id>
defaultAction: allow | deny
trustDomain: <trust-domain>
namespace: <namespace>
operations:
- name: <operation-name>
httpVerb: ["GET", "POST", ...]
action: allow | deny
appHttpPipeline:
handlers:
- name: <middleware-name>
type: <middleware-type>
httpPipeline:
handlers:
- name: <middleware-name>
type: <middleware-type>
tracing: # private regions only
samplingRate: "<float-as-string>"
otel:
endpointAddress: <url>
isSecure: <bool>
protocol: <http | grpc>
workflow:
maxConcurrentWorkflowInvocations: <int>
maxConcurrentActivityInvocations: <int>
Field reference
| Field | Notes |
|---|---|
accessControl | Service-invocation ACLs. The top-level defaultAction applies when no per-caller policy matches. Per-caller policies[] can refine to specific operations and HTTP verbs. |
appHttpPipeline | Middleware applied to traffic from the data plane to your application (inbound to the app). |
httpPipeline | Middleware applied to traffic from your application out through the data plane (outbound). |
tracing | Distributed tracing config. Only honored on projects in private regions. samplingRate is a string between "0" and "1". |
workflow | Tuning for the workflow runtime. Bounds concurrency for workflow and activity invocations. |
Worked example
apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
name: order-service-config
spec:
accessControl:
defaultAction: deny
trustDomain: public
policies:
- appId: api-gateway
defaultAction: deny
trustDomain: public
namespace: default
operations:
- name: /orders
httpVerb: ["POST"]
action: allow
workflow:
maxConcurrentWorkflowInvocations: 100
maxConcurrentActivityInvocations: 200
Applying and inspecting policies
# Apply or update
diagrid resiliency create -f resiliency.yaml --project <project>
diagrid resiliency update -f resiliency.yaml --project <project>
diagrid configuration create -f configuration.yaml --project <project>
diagrid configuration update -f configuration.yaml --project <project>
# Inspect
diagrid resiliency list --project <project>
diagrid resiliency get <name> --project <project>
diagrid configuration list --project <project>
diagrid configuration get <name> --project <project>
# Remove
diagrid resiliency delete <name> --project <project>
diagrid configuration delete <name> --project <project>
See the diagrid resiliency and diagrid configuration CLI references for the full flag set.
See also
- Policies: conceptual overview.
- Resiliency: retries, timeouts, and circuit breakers in depth.
- App IDs: how policies are bound and managed day-2.