Policies
Policies define when a version is allowed to deploy. They are the rules
that govern how releases progress through your environments — controlling
deployment timing through approvals, verification gates, progression
requirements, deployment windows, and more.
Building Confidence Through Policies
While deployments define what and how and
environments define where, policies answer the
critical question of when: is this version ready to deploy? Has it passed
through the right gates? Policies help you deploy with confidence by ensuring
that each stage meets your quality standards before progressing to the next.
Development → QA → Staging → Production
↓ ↓ ↓ ↓
(none) smoke integration full
tests tests gates
With policies, you can:
- Start simple, grow complex - Begin with basic health checks in QA, add
integration tests in staging, require approvals and verification in production
- Catch issues early - Run smoke tests in QA to catch problems before they
reach production
- Automate quality gates - Let verification results automatically determine
if a release can proceed
- Reduce deployment anxiety - Know that every production deployment has
passed through proven checks
- Customize per environment - Apply stricter rules where they matter most
Policy Structure
A policy consists of:
- Name & Description - Identify and document the policy’s purpose
- Selector - A CEL expression defining which release targets the policy
applies to
- Rules - One or more rules specifying behavior or requirements
- Priority - Higher priority policies are evaluated first
- Metadata - Arbitrary key-value pairs for organization
Policy Selectors
The selector field is a CEL expression that determines which release targets
a policy applies to. Policies only affect releases that match the selector.
Environment Selector
Target releases going to specific environments:
environment.name == "production"
environment.name in ["staging", "production"]
environment.name.startsWith("prod-")
environment.metadata['tier'] == "critical"
Resource Selector
Target releases for specific resources:
resource.kind == "Kubernetes"
resource.metadata['region'] == "us-east-1"
resource.name.contains("critical")
Deployment Selector
Target releases for specific deployments:
deployment.name == "api-service"
deployment.metadata['team'] == "platform"
Combined Selectors
Combine conditions with && (AND) and || (OR):
environment.name == "production" && deployment.metadata['tier'] == "critical"
Policy Rules
Rules define what the policy enforces. A single policy can contain multiple
rules across different types. Each rule in the rules array contains exactly
one rule type.
Approval Rule
Require manual approval before deployment:
| API Field | Terraform Attribute | Description |
|---|
anyApproval.minApprovals | min_approvals | Number of approvals needed |
See Approval for details.
Environment Progression Rule
Require successful deployment to a prerequisite environment:
| API Field | Terraform Attribute | Description |
|---|
environmentProgression.dependsOnEnvironmentSelector | depends_on_environment_selector | CEL matching prerequisite env |
environmentProgression.minimumSuccessPercentage | minimum_success_percentage | Required success % (0-100) |
environmentProgression.minimumSockTimeMinutes | minimum_sock_time_minutes | Soak time after success |
environmentProgression.maximumAgeHours | maximum_age_hours | Max age of dependency deployment |
See Environment Progression for details.
Gradual Rollout Rule
Control the pace of deployments across multiple targets:
| API Field | Terraform Attribute | Description |
|---|
gradualRollout.rolloutType | rollout_type | "linear" or "linear-normalized" |
gradualRollout.timeScaleInterval | time_scale_interval | Seconds between targets / total time |
See Gradual Rollouts for details.
Deployment Dependency Rule
Require upstream deployments to succeed first:
| API Field | Terraform Attribute | Description |
|---|
deploymentDependency.dependsOn | depends_on_selector | CEL matching upstream deployment |
See Deployment Dependency for details.
Deployment Window Rule
Control when deployments are allowed using time-based schedules:
| API Field | Terraform Attribute | Description |
|---|
deploymentWindow.rrule | rrule | RFC 5545 recurrence rule |
deploymentWindow.durationMinutes | duration_minutes | Window duration in minutes |
deploymentWindow.timezone | timezone | IANA timezone |
deploymentWindow.allowWindow | allow_window | Allow during window (deny if false) |
See Deployment Window for details.
Version Cooldown Rule
Batch frequent releases by enforcing a minimum time between deployments:
| API Field | Terraform Attribute | Description |
|---|
versionCooldown.intervalSeconds | duration | Minimum time between deploys |
See Version Cooldown for details.
Retry Rule
Configure automatic retry behavior for failed jobs:
| API Field | Terraform Attribute | Description |
|---|
retry.maxRetries | Not available | Maximum retry attempts |
retry.backoffSeconds | Not available | Seconds between retries |
retry.backoffStrategy | Not available | "linear" or "exponential" |
retry.maxBackoffSeconds | Not available | Backoff cap |
retry.retryOnStatuses | Not available | Which statuses trigger retry |
See Retry for details.
Version Selector Rule
Filter which versions can deploy to specific targets:
| API Field | Terraform Attribute | Description |
|---|
versionSelector.selector | Not available | CEL expression or JSON selector |
versionSelector.description | Not available | Human-readable description |
See Version Selector for details.
Verification Rule
Run automated checks after deployment:
See Verification for detailed configuration options.
The Terraform provider supports the following policy blocks:
| Block | Description |
|---|
any_approval | Require manual approvals |
environment_progression | Require success in prerequisite environments |
gradual_rollout | Stagger deployments over time |
deployment_dependency | Require upstream deployments to succeed first |
deployment_window | Time-based deployment scheduling |
version_cooldown | Batch frequent releases |
verification | Automated health checks |
retry and version_selector are not yet available in the Terraform
provider. Use the REST API for these rule types.
REST API Reference
Create a policy:
POST /v1/workspaces/{workspaceId}/policies
Get/Update/Delete a policy:
GET /v1/workspaces/{workspaceId}/policies/{policyId}
PUT /v1/workspaces/{workspaceId}/policies/{policyId}
DELETE /v1/workspaces/{workspaceId}/policies/{policyId}
List policies:
GET /v1/workspaces/{workspaceId}/policies
Each rule in the rules array is an object with exactly one rule-type key
(e.g., anyApproval, gradualRollout, deploymentWindow).
Policy Evaluation
When a release is created, Ctrlplane:
- Finds matching policies - Evaluates the
selector CEL expression
against each release target
- Merges rules - Combines rules from all matching policies
- Applies rules - Enforces each rule type
Rule Interactions
- Approval + Gradual Rollout: The rollout start time is determined by when
the approval was satisfied
- Environment Progression + Gradual Rollout: The rollout waits until
progression criteria are met
- Deployment Window + Gradual Rollout: Allow windows push the rollout start
to the window opening; deny windows pause the rollout
- Version Cooldown + Deployment Window: Both must be satisfied — cooldown
determines which version, window determines when
Common Patterns
Environment Progression
Different requirements per environment:
Critical Service Protection
Extra protection for critical services:
resource "ctrlplane_policy" "critical_service_gates" {
name = "Critical Service Gates"
selector = "deployment.metadata['tier'] == 'critical' && environment.name == 'production'"
priority = 20
any_approval {
min_approvals = 2
}
gradual_rollout {
rollout_type = "linear"
time_scale_interval = 600
}
}
Best Practices
Policy Organization
- ✅ Use descriptive policy names
- ✅ Document policy purpose in description
- ✅ Start with permissive policies and tighten over time
- ✅ Test policies in lower environments first
- ✅ Use
priority to control evaluation order for overlapping policies
Selector Design
- ✅ Be specific with selectors to avoid unexpected matches
- ✅ Use environment selectors for environment-specific rules
- ✅ Use metadata for cross-cutting concerns (team, tier, etc.)
- ✅ Test selector expressions before applying
Rule Configuration
- ✅ Set reasonable timeouts and failure limits
- ✅ Use verification to catch issues before they impact users
- ✅ Require approvals for high-risk deployments
- ✅ Use gradual rollouts for large-scale deployments
- ✅ Combine complementary rules (e.g., approval + gradual rollout)
Next Steps