Skip to main content

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
diagrid workflow access-policy create -f workflow-access-policy.yaml --project my-project

Manifest envelope

Every policy manifest shares the same top-level shape:

apiVersion: dapr.io/v1alpha1
kind: <Resiliency | Configuration | WorkflowAccessPolicy>
metadata:
name: <policy-name>
scopes:
- <app-id-1>
- <app-id-2>
spec:
# ...kind-specific spec below
FieldTypeRequiredDescription
apiVersionstringyesMust be dapr.io/v1alpha1.
kindstringyesResiliency, Configuration, or WorkflowAccessPolicy.
metadata.namestringyesUnique policy name within the project.
scopesstring[]noApp IDs the policy applies to. Top-level (sibling of spec). Omit to leave the policy unbound — except for WorkflowAccessPolicy, where omitting scopes applies the policy to every app in the project.

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

FieldTypeDescription
policyconstant | exponentialBackoff shape. Constant waits duration between attempts; exponential grows the wait up to maxInterval.
durationduration string (e.g. 5s)Wait between attempts (constant) or initial wait (exponential).
maxIntervalduration stringUpper bound on the wait for exponential policies. Ignored for constant.
maxRetriesintMaximum attempts after the initial call. -1 means retry indefinitely.
matching.httpStatusCodesstringComma-separated HTTP codes or ranges to retry, e.g. "500,501,502,503,504". Unmatched codes fail immediately.
matching.gRPCStatusCodesstringComma-separated gRPC status codes to retry, e.g. "14,4,8".

Circuit-breaker fields

FieldTypeDescription
maxRequestsintNumber of probe requests permitted while the breaker is half-open.
intervalduration stringSliding window over which failures are counted.
timeoutduration stringTime the breaker stays open before transitioning to half-open.
tripCEL expressionTrip condition. Evaluated against the variables below, e.g. "consecutiveFailures > 5".

The trip expression is evaluated as CEL with the following variables in scope:

VariableDescription
requestsTotal requests observed in the current window.
consecutiveFailuresConsecutive failures since the last success.
consecutiveSuccessesConsecutive successes since the last failure.
totalFailuresTotal failures in the current window.
totalSuccessesTotal 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:

DimensionDefault value
Timeout10s
Retryconstant, 5s between attempts, 5 retries, matching HTTP 500,501,502,503,504 and gRPC 14,4,8
Circuit breakermaxRequests: 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. For the access-control rules model and the CLI commands to manage them, see Secure service invocation with access control.

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

FieldNotes
accessControlService-invocation ACLs. The top-level defaultAction applies when no per-caller policy matches. Per-caller policies[] can refine to specific operations and HTTP verbs.
appHttpPipelineMiddleware applied to traffic from the data plane to your application (inbound to the app).
httpPipelineMiddleware applied to traffic from your application out through the data plane (outbound).
tracingDistributed tracing config. Only honored on projects in private regions. samplingRate is a string between "0" and "1".
workflowTuning 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

Workflow access policy

A workflow access policy is an allow-list that controls which caller App IDs can schedule workflows and activities on the App IDs in scopes. Without a policy, all cross-app workflow calls are allowed; once a policy covers an app, every cross-app call must match a rule or it is denied. Self-calls are always allowed. For the conceptual story and CLI walkthrough see Secure workflows with access policies.

Spec

spec:
rules:
- callers:
- appID: <caller-app-id>
workflows:
- name: <workflow-name or glob>
operations: [schedule]
activities:
- name: <activity-name or glob>

Field reference

FieldTypeRequiredDescription
ruleslistnoAllow-list of rules; a call is permitted if any rule matches. An empty or omitted list denies every cross-app workflow call to the scoped apps.
rules[].callerslistyesCaller App IDs this rule grants access to. At least one entry.
rules[].callers[].appIDstringyesThe App ID of the calling application.
rules[].workflowslistno*Workflow rules granted to the matched callers.
rules[].workflows[].namestringyesExact workflow name or glob pattern (*, ?, [abc]).
rules[].workflows[].operationsstring[]yesSet to [schedule]. The API also accepts terminate, raise, pause, resume, purge, get, and rerun for forward compatibility, but these operations don't route cross-app yet, so policies have no effect on them.
rules[].activitieslistno*Activity rules granted to the matched callers. Activities only support scheduling, so there is no operations field.
rules[].activities[].namestringyesExact activity name or glob pattern.

* At least one of workflows or activities must be present in each rule.

Worked example

apiVersion: dapr.io/v1alpha1
kind: WorkflowAccessPolicy
metadata:
name: order-app-policy
scopes:
- order-app
spec:
rules:
- callers:
- appID: orchestrator-app
workflows:
- name: order-processing
operations: [schedule]
- name: "report-*"
operations: [schedule]
activities:
- name: charge-payment

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 apply -f configuration.yaml --project <project> # replace in place; configuration update takes only --policy/--default-action flags
diagrid workflow access-policy create -f workflow-access-policy.yaml --project <project>
diagrid workflow access-policy update -f workflow-access-policy.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>
diagrid workflow access-policy list --project <project>
diagrid workflow access-policy get <name> --project <project>

# Remove
diagrid resiliency delete <name> --project <project>
diagrid configuration delete <name> --project <project>
diagrid workflow access-policy delete <name> --project <project>

See the diagrid resiliency and diagrid configuration CLI references for the full flag set.

See also