Skip to main content
Deployment dependency rules ensure that one deployment succeeds before another can proceed. Use them to coordinate related services, enforce deployment order across microservices, or manage infrastructure dependencies.

Overview

Why Use Deployment Dependencies?

Deployment dependency rules help you:
  • Coordinate services - Deploy database before API, API before frontend
  • Manage infrastructure - Infrastructure changes before application updates
  • Enforce order - Shared libraries before dependent services
  • Reduce failures - Prevent cascading failures from out-of-order deploys

Configuration

resource "ctrlplane_policy" "api_requires_database" {
  name     = "API Requires Database"
  selector = "deployment.name == 'api-service'"

  deployment_dependency {
    depends_on_selector = "deployment.name == 'database-migration'"
  }
}

Properties

deploymentDependency.dependsOn
string
required
CEL expression to match upstream release targets that must exist before this deployment can proceed. The expression can reference both deployment and version properties of the currently deployed upstream release.

Available CEL Variables

The dependsOn expression is evaluated against each release target on the same resource that has a successful release. Both deployment.* and version.* fields are available:
VariableTypeDescription
deployment.idstringDeployment ID
deployment.namestringDeployment name
deployment.slugstringDeployment slug
deployment.metadatamapDeployment metadata key-value pairs
version.idstringDeployed version ID
version.tagstringVersion tag (e.g. v2.1.0)
version.namestringVersion name
version.statusstringVersion status
version.metadatamapVersion metadata key-value pairs
version.createdAttimestampWhen the version was created

How It Works

  1. Release created - A new version is released for a deployment with dependency rules.
  2. Same-resource resolution - Ctrlplane finds all release targets on the same resource as the current target.
  3. Version resolution - For each release target, Ctrlplane resolves the deployment and its currently deployed version (from the latest successful job).
  4. CEL evaluation - The dependsOn expression is evaluated against each {deployment, version} pair.
  5. Deployment allowed - If at least one upstream release target matches the selector, the deployment can proceed.

Common Patterns

Database Before API

Ensure database migrations complete before API deploys:
resource "ctrlplane_policy" "api_requires_db" {
  name     = "API Requires DB Migration"
  selector = "deployment.name == 'api-service'"

  deployment_dependency {
    depends_on_selector = "deployment.name == 'database-migration'"
  }
}

Service Dependency Chain

Create a chain of dependencies:
resource "ctrlplane_policy" "api_depends_on_db" {
  name     = "API Depends on DB"
  selector = "deployment.name == 'api-service'"

  deployment_dependency {
    depends_on_selector = "deployment.name == 'database-migration'"
  }
}

resource "ctrlplane_policy" "frontend_depends_on_api" {
  name     = "Frontend Depends on API"
  selector = "deployment.name == 'frontend'"

  deployment_dependency {
    depends_on_selector = "deployment.name == 'api-service'"
  }
}

Shared Library Dependencies

Ensure shared libraries are deployed before dependent services:
resource "ctrlplane_policy" "services_require_shared_lib" {
  name     = "Services Require Shared Lib"
  selector = "deployment.metadata['usesSharedLib'] == 'true'"

  deployment_dependency {
    depends_on_selector = "deployment.metadata['type'] == 'shared-library'"
  }
}

Version-Scoped Dependencies

Require a specific version range of an upstream deployment:
resource "ctrlplane_policy" "api_requires_db_v2" {
  name     = "API Requires DB Migration v2"
  selector = "deployment.name == 'api-service'"

  deployment_dependency {
    depends_on_selector = "deployment.name == 'database-migration' && version.tag.startsWith('v2.')"
  }
}

Version Metadata Filtering

Depend on an upstream deployment running a version with specific metadata:
resource "ctrlplane_policy" "frontend_requires_stable_api" {
  name     = "Frontend Requires Stable API"
  selector = "deployment.name == 'frontend'"

  deployment_dependency {
    depends_on_selector = "deployment.name == 'api-service' && version.metadata.channel == 'stable'"
  }
}

Infrastructure First

Deploy infrastructure changes before application updates:
resource "ctrlplane_policy" "app_requires_infrastructure" {
  name     = "App Requires Infrastructure"
  selector = "deployment.metadata['type'] == 'application'"

  deployment_dependency {
    depends_on_selector = "deployment.metadata['type'] == 'infrastructure'"
  }
}

Multi-Service Dependency

Depend on multiple services using CEL in operator:
resource "ctrlplane_policy" "gateway_requires_services" {
  name     = "Gateway Requires Backend Services"
  selector = "deployment.name == 'api-gateway'"

  deployment_dependency {
    depends_on_selector = "deployment.name in ['auth-service', 'user-service', 'billing-service']"
  }
}

Combining with Other Rules

With Environment Progression

resource "ctrlplane_policy" "api_full_gates" {
  name     = "API Full Gates"
  selector = "deployment.name == 'api-service' && environment.name == 'production'"

  deployment_dependency {
    depends_on_selector = "deployment.name == 'database-migration'"
  }

  environment_progression {
    depends_on_environment_selector = "environment.name == 'staging'"
  }

  any_approval {
    min_approvals = 1
  }
}

With Gradual Rollout

resource "ctrlplane_policy" "frontend_controlled_release" {
  name     = "Frontend Controlled Release"
  selector = "deployment.name == 'frontend'"

  deployment_dependency {
    depends_on_selector = "deployment.name == 'api-service'"
  }

  gradual_rollout {
    rollout_type        = "linear"
    time_scale_interval = 300
  }
}

Best Practices

Dependency Design

PatternUse Case
Database → APISchema changes before code
API → FrontendAPI contracts before consumers
Infrastructure → AppPlatform changes before workloads
Shared lib → ServicesCommon code before dependents
Config → ApplicationConfiguration before apps

Recommendations

  • ✅ Keep dependency chains short (2-3 levels max)
  • ✅ Use metadata to group related deployments
  • ✅ Document why dependencies exist
  • ✅ Test dependency resolution in staging
  • ✅ Monitor for circular dependency issues

Anti-Patterns

  • ❌ Deep dependency chains (> 3 levels)
  • ❌ Circular dependencies (A → B → A)
  • ❌ Over-coupling unrelated services
  • ❌ Using dependencies when environment progression would suffice

Troubleshooting

Deployment Blocked

If a deployment is blocked waiting for dependencies:
  1. Check the dependency deployment’s status
  2. Verify the CEL expression matches the expected deployment
  3. Remember that dependencies are resolved per-resource — the upstream deployment must have a successful release on the same resource
  4. Review the dependency deployment’s success status

Circular Dependencies

If you encounter circular dependency errors:
  1. Review the dependency graph
  2. Break the cycle by removing one dependency
  3. Consider using environment progression instead

Next Steps