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 deployment(s) that must have a successful release before this deployment can proceed.

How It Works

  1. Release created - A new version is released for a deployment with dependency rules.
  2. Dependency check - Ctrlplane evaluates the dependsOn CEL expression to find matching upstream deployments.
  3. Same-resource resolution - For each matching upstream deployment, Ctrlplane looks for a release target on the same resource as the current target. This means the dependency is resolved per-resource, not globally.
  4. Status evaluation - Each upstream release target must have a latest completed job with a successful status.
  5. Deployment allowed - Once all upstream dependencies are satisfied, 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'"
  }
}

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