Orchestrates complex multi-stage deployments with dependency management,
Scanned 9/4/2026
Install to Claude Code
npx -y skills add paulpas/agent-skill-router --skill deployment-orchestration --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Deployment Orchestration?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/paulpas-deployment-orchestration)More formats (shields.io, HTML) on the badges page.
---
name: deployment-orchestration
compatibility: opencode
completeness: 95
content-types:
- guidance
- examples
- do-dont
- config
description: Orchestrates complex multi-stage deployments with dependency management,
sequencing rules, and failure handling across interconnected services.
license: MIT
maturity: stable
metadata:
completeness: 95
content-types:
- code
- guidance
- config
- do-dont
domain: cncf
exampleCount: 3
maturity: stable
output-format: code
related-skills: deployment-philosophy,canary-deployment,blue-green-deployment,state-management
role: implementation
scope: infrastructure
triggers: deployment orchestration, multi-stage deployment, deployment pipeline,
service dependency, deployment sequencing, coordinated deployment
archetypes:
- tactical
anti_triggers:
- brainstorming
- vague ideation
- non-containerized architecture
response_profile:
verbosity: low
directive_strength: high
abstraction_level: operational
version: "1.0.0"
---
---
# Deployment Orchestration
Orchestrates coordinated multi-service deployments with dependency-aware sequencing, failure containment, and automatic rollback across service boundaries. Ensures that when multiple services deploy together, their compatibility constraints are respected.
## TL;DR Checklist
- [ ] Map service dependencies before defining deployment order
- [ ] Define deployment batches — groups of services that can deploy together
- [ ] Set health gates at each batch boundary
- [ ] Ensure rollback handles cross-service compatibility
- [ ] Validate API contract compatibility before deploying consumers
---
## When to Use
Use this skill when:
- **Multiple services deploy together** — A change spans 2+ services that must be deployed in coordination
- **Service dependencies exist** — Service A depends on Service B's API contract, and the change may break that contract
- **Database and application deploy together** — Schema changes in a database must be deployed alongside application code that uses it
- **Coordinated rollout is safer** — Deploying services independently risks incompatible versions running simultaneously
---
## When NOT to Use
Avoid this skill for:
- **Single-service deployments** — If only one service is changing, orchestration overhead is wasted
- **Services with no shared dependencies** — Independent services should deploy independently
- **Frequent independent updates** — If services deploy 10+ times per day independently, orchestration becomes a bottleneck
---
## Core Workflow
### 1. Map Service Dependencies
Document all inter-service dependencies: API contracts, shared data schemas, event streams, and configuration dependencies. Build a dependency graph.
**Checkpoint:** You have a complete dependency graph showing which services depend on which others.
### 2. Define Deployment Batches
Group services into batches based on dependency direction. Services with no mutual dependencies can deploy in parallel. Services that depend on each other must deploy sequentially.
**Checkpoint:** Each batch's internal order respects dependency constraints, and batches between each other can run in parallel.
### 3. Define Compatibility Windows
For each dependency pair, define the compatibility window: what versions of each service can coexist during the transition.
**Checkpoint:** You know the exact version compatibility matrix for every dependency pair.
### 4. Execute with Health Gates
Deploy each batch, wait for health gates, then proceed to the next batch. Parallel batches execute simultaneously when their health gates pass.
**Checkpoint:** All services in the batch pass health checks before the next batch starts.
### 5. Handle Failures
If any service in a batch fails its health check, stop all parallel batches, roll back the failed batch, and decide whether to retry or abort.
**Checkpoint:** Rollback order is the reverse of deployment order to maintain compatibility.
---
## Implementation Patterns
### Pattern 1: Dependency Graph and Batch Ordering
Build a dependency graph and compute deployment batches using topological sorting.
#### ❌ BAD — Linear Deployment Without Dependency Awareness
```bash
# ❌ BAD: Deploying services in arbitrary order ignores dependencies
# order-service depends on user-service API — deploying order first will fail
SERVICES=("payment-service" "user-service" "order-service" "notification-service")
for service in "${SERVICES[@]}"; do
kubectl set image deployment/$service app=app:latest
kubectl rollout status deployment/$service
done
# Problem: order-service might depend on user-service API
# Problem: notification-service might depend on order-service events
# Problem: payment-service might depend on both
# Deploying in this order risks incompatible versions running simultaneously
```
**What's wrong:**
- No dependency awareness — services deploy in arbitrary order
- Incompatible versions may run simultaneously during transition
- No rollback coordination across services
- Failure in one service leaves others in an inconsistent state
#### ✅ GOOD — Dependency-Aware Batch Deployment
```bash
# ✅ GOOD: Dependency-aware batch deployment with topological sort
# Services with no mutual dependencies deploy in parallel; dependent services deploy sequentially
# --- Dependency graph definition (JSON) ---
# {
# "dependencies": {
# "payment-service": ["user-service"],
# "order-service": ["user-service", "payment-service"],
# "notification-service": ["order-service"]
# }
# }
DEPS_FILE="/tmp/dependency-graph.json"
# --- Topological sort using Kahn's algorithm ---
compute_batches() {
local deps_file=$1
local batch_dir
batch_dir=$(mktemp -d)
# Build adjacency list and in-degree count
local all_services
all_services=$(jq -r 'keys[]' "$deps_file")
local service_count
service_count=$(echo "$all_services" | wc -l)
# Initialize in-degree for all services
declare -A in_degree
for svc in $all_services; do
in_degree[$svc]=0
done
# Count in-degrees
for svc in $all_services; do
local deps
deps=$(jq -r ".dependencies.\"$svc\" // [] | .[]" "$deps_file" 2>/dev/null)
if [[ -n "$deps" ]]; then
in_degree[$svc]=$(echo "$deps" | wc -l)
fi
done
# Find initial zero in-degree services
local batch_num=0
local processed=0
local remaining_services="$all_services"
while [[ $processed -lt $service_count ]]; do
local current_batch=()
# Find services with in-degree 0
for svc in $remaining_services; do
if [[ ${in_degree[$svc]} -eq 0 ]]; then
current_batch+=("$svc")
fi
done
if [[ ${#current_batch[@]} -eq 0 ]]; then
echo "❌ ERROR: Circular dependency detected among remaining services"
echo "Remaining: $remaining_services"
return 1
fi
# Record this batch
local batch_id="batch-$batch_num"
echo "${current_batch[*]}" > "$batch_dir/$batch_id"
echo " Batch $batch_num: ${current_batch[*]}"
# Update in-degrees for next round
for svc in "${current_batch[@]}"; do
# Find services that depend on this one
for other_svc in $remaining_services; do
local deps
deps=$(jq -r ".dependencies.\"$other_svc\" // [] | .[]" "$deps_file" 2>/dev/null)
if echo "$deps" | grep -qx "$svc"; then
in_degree[$other_svc]=$(( ${in_degree[$other_svc]} - 1 ))
fi
done
done
# Remove processed services
remaining_services=$(echo "$remaining_services" | grep -v -x "$(printf '%s\n' "${current_batch[@]}")")
processed=$((processed + ${#current_batch[@]}))
batch_num=$((batch_num + 1))
done
# Output batch files
echo "$batch_dir"
}
# --- Health check function ---
check_service_health() {
local service=$1
local http_code
http_code=$(curl -s -o /dev/null -w "%{http_code}" \
--max-time 5 "http://${service}:8080/health" 2>/dev/null)
[[ "$http_code" == "200" ]]
}
# --- Deploy a single service ---
deploy_service() {
local service=$1 version=$2
echo " Deploying $service → $version"
kubectl set image deployment/$service app=$version
kubectl rollout status deployment/$service --timeout=120s
}
# --- Rollback a single service ---
rollback_service() {
local service=$1
echo " Rolling back $service"
kubectl rollout undo deployment/$service
}
# --- Main orchestration ---
orchestrate_deployment() {
local version=$1
echo "=== Multi-Service Deployment Orchestration ==="
echo "Target version: $version"
echo "Computing deployment batches..."
echo ""
# Compute batches
local batch_dir
batch_dir=$(compute_batches "$DEPS_FILE")
echo ""
# Deploy each batch sequentially
local batch_num=0
local batch_file="$batch_dir/batch-$batch_num"
local deployment_results=()
while [[ -f "$batch_file" ]]; do
local batch_services
read -r -a batch_services < "$batch_file"
echo "--- Batch $batch_num: ${batch_services[*]} ---"
local batch_success=true
local failed_service=""
# Deploy all services in batch
for service in "${batch_services[@]}"; do
if ! deploy_service "$service" "$version"; then
batch_success=false
failed_service=$service
break
fi
done
if [[ "$batch_success" != true ]]; then
echo "❌ Deployment failed for $failed_service — rolling back"
for service in "${batch_services[@]}"; do
rollback_service "$service"
done
return 1
fi
# Health gate for all services in batch
for service in "${batch_services[@]}"; do
if ! check_service_health "$service"; then
echo "❌ Health check failed for $service — rolling back batch"
for svc in "${batch_services[@]}"; do
rollback_service "$svc"
done
return 1
fi
done
echo "✅ Batch $batch_num passed — all services healthy"
deployment_results+=("batch-$batch_num:PASS")
batch_num=$((batch_num + 1))
batch_file="$batch_dir/batch-$batch_num"
done
echo ""
echo "=== Deployment Complete ==="
for result in "${deployment_results[@]}"; do
echo " $result"
done
}
# --- Rollback in reverse order ---
rollback_deployment() {
local batch_dir=$1
echo "=== Rolling back deployment (reverse order) ==="
local batch_num=$(( $(ls "$batch_dir" | sort -t'-' -k2 -n | tail -1 | cut -d'-' -f2) - 1 ))
while [[ $batch_num -ge 0 ]]; do
local batch_file="$batch_dir/batch-$batch_num"
if [[ -f "$batch_file" ]]; then
read -r -a batch_services < "$batch_file"
echo "Rolling back batch $batch_num: ${batch_services[*]}"
for service in "${batch_services[@]}"; do
rollback_service "$service"
done
fi
batch_num=$((batch_num - 1))
done
}
# --- Usage ---
# orchestrate_deployment "app:v2.0.0"
```
### Pattern 2: Compatibility Window Manager
Track version compatibility windows to ensure safe transitions during deployment.
#### ✅ GOOD — Version Compatibility Validation
```bash
# ✅ GOOD: Validate version compatibility before deploying each service
# Checks that target version is compatible with currently running dependencies
# --- Compatibility windows (JSON) ---
# Defines which version combinations are safe for each service dependency pair
COMPLIANCE_FILE="/tmp/compatibility-windows.json"
# [
# {
# "provider": "user-service",
# "consumer": "order-service",
# "provider_min": "1.0.0",
# "provider_max": "1.5.0",
# "consumer_min": "2.0.0",
# "consumer_max": "2.5.0"
# }
# ]
# --- Version comparison (simple semver string comparison) ---
version_in_range() {
local version=$1 min_ver=$2 max_ver=$3
[[ "$version" > "$min_ver" || "$version" == "$min_ver" ]] && \
[[ "$version" < "$max_ver" || "$version" == "$max_ver" ]]
}
# --- Validate a service deployment against compatibility windows ---
validate_deployment() {
local service=$1 target_version=$2 running_versions_file=$3
echo "Validating deployment: $service@$target_version"
local violations=()
# Check provider windows (service is the provider)
while IFS= read -r window; do
local provider consumer provider_min provider_max consumer_min consumer_max
provider=$(echo "$window" | jq -r '.provider')
consumer=$(echo "$window" | jq -r '.consumer')
provider_min=$(echo "$window" | jq -r '.provider_min')
provider_max=$(echo "$window" | jq -r '.provider_max')
consumer_min=$(echo "$window" | jq -r '.consumer_min')
consumer_max=$(echo "$window" | jq -r '.consumer_max')
if [[ "$provider" == "$service" ]]; then
local running_consumer
running_consumer=$(jq -r ".\"$consumer\" // empty" "$running_versions_file")
if [[ -n "$running_consumer" ]]; then
if ! version_in_range "$target_version" "$provider_min" "$provider_max"; then
violations+=("Deploying $service@$target_version incompatible with $consumer@$running_consumer (requires $consumer@$consumer_min-$consumer_max)")
fi
fi
fi
# Check consumer windows (service is the consumer)
if [[ "$consumer" == "$service" ]]; then
local running_provider
running_provider=$(jq -r ".\"$provider\" // empty" "$running_versions_file")
if [[ -n "$running_provider" ]]; then
if ! version_in_range "$target_version" "$consumer_min" "$consumer_max"; then
violations+=("Deploying $service@$target_version incompatible with $provider@$running_provider (requires $provider@$provider_min-$provider_max)")
fi
fi
fi
done < <(jq -c '.[]' "$COMPLIANCE_FILE")
if [[ ${#violations[@]} -gt 0 ]]; then
echo "❌ Compatibility violations:"
for v in "${violations[@]}"; do
echo " - $v"
done
return 1
else
echo "✅ Compatible with all running services"
return 0
fi
}
# --- Get running versions from cluster ---
get_running_versions() {
local services=$@
local versions_json="{}"
for service in $services; do
local version
version=$(kubectl get deployment "$service" -o jsonpath='{.spec.template.metadata.labels.version}' 2>/dev/null)
if [[ -n "$version" ]]; then
versions_json=$(echo "$versions_json" | jq --arg s "$service" --arg v "$version" '. + {($s): $v}')
fi
done
echo "$versions_json"
}
# --- Usage ---
# running=$(get_running_versions user-service order-service payment-service notification-service)
# echo "$running" > /tmp/running-versions.json
# validate_deployment order-service "2.1.0" /tmp/running-versions.json
```
### Pattern 3: Deployment State Machine
Track the state of a multi-service deployment for observability and recovery.
#### ✅ GOOD — File-Based Deployment State Tracking
```bash
# ✅ GOOD: Track multi-service deployment state for observability and recovery
# Uses file-based state machine for crash recovery and audit trail
# --- State file configuration ---
DEPLOYMENT_ID="deploy-$(date +%Y%m%d-%H%M%S)"
STATE_DIR="/tmp/deployment-state/$DEPLOYMENT_ID"
STATE_FILE="$STATE_DIR/state.json"
HISTORY_FILE="$STATE_DIR/history.json"
# --- Initialize state ---
init_state() {
local total_batches=$1
mkdir -p "$STATE_DIR"
jq -n \
--arg id "$DEPLOYMENT_ID" \
--arg phase "planning" \
--argjson total "$total_batches" \
--arg started "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
'{
deployment_id: $id,
phase: $phase,
current_batch: "",
total_batches: $total,
completed_batches: 0,
failed_service: "",
error: "",
started_at: $started,
completed_at: null
}' > "$STATE_FILE"
echo "[]" > "$HISTORY_FILE"
}
# --- Record state transition ---
record_state() {
local phase=$1 batch_id=${2:-}
local timestamp
timestamp=$(date -u +%Y-%m-%dT%H:%M:%SZ)
# Update main state
local state
state=$(cat "$STATE_FILE")
state=$(echo "$state" | jq --arg p "$phase" --arg b "$batch_id" '.phase = $p | .current_batch = $b')
# Add to history
local history
history=$(cat "$HISTORY_FILE")
jq --arg ts "$timestamp" --argjson s "$state" \
'. + [{timestamp: $ts, state: $s}]' "$HISTORY_FILE" > "${HISTORY_FILE}.tmp"
mv "${HISTORY_FILE}.tmp" "$HISTORY_FILE"
echo "$state" > "$STATE_FILE"
}
# --- Advance batch ---
advance_batch() {
local batch_id=$1
local state
state=$(cat "$STATE_FILE")
local completed
completed=$(echo "$state" | jq -r '.completed_batches')
echo "Advancing batch: $batch_id (completed: $((completed + 1)))"
jq --arg b "$batch_id" '.current_batch = $b | .completed_batches += 1 | .phase = "verifying"' \
"$STATE_FILE" > "${STATE_FILE}.tmp"
mv "${STATE_FILE}.tmp" "$STATE_FILE"
record_state "verifying" "$batch_id"
}
# --- Verify complete ---
verify_complete() {
echo "Verification phase complete"
jq '.phase = "deploying"' "$STATE_FILE" > "${STATE_FILE}.tmp"
mv "${STATE_FILE}.tmp" "$STATE_FILE"
record_state "deploying"
}
# --- Mark failure ---
mark_failed() {
local service=$1 error=$2
local timestamp
timestamp=$(date -u +%Y-%m-%dT%H:%M:%SZ)
jq --arg s "$service" --arg e "$error" --arg t "$timestamp" \
'.phase = "failed" | .failed_service = $s | .error = $e | .completed_at = $t' \
"$STATE_FILE" > "${STATE_FILE}.tmp"
mv "${STATE_FILE}.tmp" "$STATE_FILE"
record_state "failed"
}
# --- Mark rollback ---
mark_rollback() {
echo "Beginning rollback phase"
jq '.phase = "rolling_back"' "$STATE_FILE" > "${STATE_FILE}.tmp"
mv "${STATE_FILE}.tmp" "$STATE_FILE"
record_state "rolling_back"
}
# --- Mark complete ---
mark_complete() {
local timestamp
timestamp=$(date -u +%Y-%m-%dT%H:%M:%SZ)
jq --arg t "$timestamp" '.phase = "complete" | .completed_at = $t' \
"$STATE_FILE" > "${STATE_FILE}.tmp"
mv "${STATE_FILE}.tmp" "$STATE_FILE"
record_state "complete"
}
# --- Get state ---
get_state() {
cat "$STATE_FILE" 2>/dev/null || echo "{}"
}
get_progress() {
local state
state=$(get_state)
local total completed
total=$(echo "$state" | jq -r '.total_batches')
completed=$(echo "$state" | jq -r '.completed_batches')
if [[ "$total" -eq 0 ]]; then
echo "0%"
else
echo "$(( (completed * 100) / total ))%"
fi
}
# --- Usage ---
# init_state 3
# advance_batch "batch-0"
# verify_complete
# mark_complete
# get_state | jq . # View current state
# cat "$HISTORY_FILE" | jq . # View state history
```
---
## Configuration Examples
### Deployment Configuration
```yaml
deployment:
strategy: batch_with_gates
parallel_limit: 3 # Max services deploying simultaneously
health_gate:
min_healthy_instances: 0.8
error_rate_threshold: 0.01
latency_p99_threshold_ms: 500
rollback:
auto_rollback: true
on_failure: all_previous_batches
order: reverse_topological
compatibility:
require_validation: true
window_timeout_hours: 24
```
---
## Constraints
### MUST DO
- **Always map dependencies before deployment** — Unknown dependencies are the most dangerous kind
- **Compute deployment order from the dependency graph** — Never guess deployment order
- **Validate compatibility before each batch** — Check version compatibility between running and deploying versions
- **Use reverse topological order for rollback** — Rollback must undo dependencies before dependents
- **Track deployment state for recovery** — If a deployment crashes mid-way, you need to know where it stopped
- **Define health gates for every batch** — No batch proceeds without health verification
### MUST NOT DO
- **Never deploy dependent services in the same batch** — If service B depends on service A, they must be in different batches
- **Never skip health gates to "save time"** — Fast failures are good; unverified deployments are liabilities
- **Never assume backward compatibility without checking** — Explicitly document and validate compatibility windows
- **Never deploy more services in a batch than necessary** — Larger batches = larger blast radius
- **Never deploy without a rollback plan** — If you can't rollback, you can't deploy
---
## Philosophy Alignment
This skill adheres to the **5 Laws of Elegant Defense**:
### Early Exit
- Deployment halts at the first health gate failure — no progression to subsequent batches
- Compatibility validation fails fast — incompatible versions never reach deployment
### Parse Don't Validate
- Dependency graph is parsed and computed once at the start
- Internal logic trusts the topological sort result, never re-validates
### Atomic Predictability
- Batch deployment is independently testable: same dependencies + same versions = same batch order
- Compatibility check is a pure function — same inputs always produce same result
### Fail Fast
- Any service health failure stops all parallel batches immediately
- Compatibility violation halts deployment before any service is deployed
### Intentional Naming
- `DependencyGraph`, `ServiceBatch`, `CompatibilityWindow` — names describe domain concepts
- `rollback_order()` vs `compute_batches()` — operations are self-documenting
---
## Related Skills
| Skill Name | When to Use | Relationship |
|------------|------------|--------------|
| `deployment-philosophy` | Use **before** this skill to determine if multi-service orchestration is needed | Prerequisite: strategy assessment |
| `canary-deployment` | Use **alongside** when individual services within a batch use canary | Complementary: canary within orchestration |
| `blue-green-deployment` | Use **alongside** when services use blue-green for zero-downtime | Complementary: blue-green within orchestration |
| `state-management` | Use **alongside** when database/schema changes coordinate with application deployment | Complementary: data + code coordination |
---
## Output Template
When applying this skill, your output should contain:
1. **Dependency Graph** — Service dependencies and deployment batches
2. **Compatibility Windows** — Version compatibility for each dependency pair
3. **Deployment Sequence** — Ordered list of batches with parallel groups
4. **Health Gates** — Per-batch health check criteria
5. **Rollback Plan** — Reverse-order rollback with compatibility verification
---
**Skill Version:** 1.0.0
**Created:** 2026-05-15
**Maturity:** stable
**Completeness:** 95%
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!