Provides release management strategies including deployment patterns, version control, and rollback procedures. Use when planning releases, managing deployments, or when user mentions 'release', 'canary', 'blue-green', 'rollback', 'feature flag', 'release train', 'semantic versioning', 'changelog', 'migration'.
Provides release management strategies including deployment patterns, version control, and rollback procedures. Use when planning releases, managing deployments, or when user mentions 'release', 'canary', 'blue-green', 'rollback', 'feature flag', 'release train', 'semantic versioning', 'changelog', 'migration'.
type
skill
category
ops
status
stable
origin
tibsfox
modified
false
first_seen
"2026-02-07T00:00:00.000Z"
first_path
examples/release-management/SKILL.md
superseded_by
null
Release Management
Best practices for shipping software reliably through structured release processes, deployment strategies, and rollback automation.
Deployment Strategy Comparison
Choosing the right deployment strategy depends on risk tolerance, infrastructure budget, and rollback requirements.
Strategy
Zero Downtime
Rollback Speed
Infrastructure Cost
Complexity
Best For
Blue-Green
Yes
Instant (switch)
2x
Medium
Critical services, compliance
Canary
Yes
Fast (route away)
1.05-1.5x
High
High-traffic user-facing apps
Rolling
Yes
Slow (re-deploy)
1x
Low
Stateless microservices
Recreate
No (brief outage)
Slow (re-deploy)
1x
Low
Dev/staging, batch jobs
A/B Testing
Yes
Fast (route away)
1.2-1.5x
High
Feature experimentation
Shadow/Dark
Yes
N/A (no user impact)
1.5-2x
Very High
ML models, data pipelines
Decision Matrix
Is the service stateful?
YES --> Can you afford 2x infrastructure?
YES --> Blue-Green
NO --> Rolling (with drain + health checks)
NO --> Is it high-traffic (>1000 rps)?
YES --> Canary (gradual rollout)
NO --> Rolling (simple, cost-effective)
Canary Deployment Configuration
Kubernetes Canary with Argo Rollouts
# argo-rollout.yaml -- Progressive canary with automated analysisapiVersion:argoproj.io/v1alpha1kind:Rolloutmetadata:name:payment-servicenamespace:productionspec:replicas:10revisionHistoryLimit:3selector:matchLabels:app:payment-servicestrategy:canary:# Canary traffic steps with pause for analysissteps:-setWeight:5-pause: { duration:5m } # 5% for 5 minutes-analysis:templates:-templateName:canary-success-rateargs:-name:service-namevalue:payment-service-setWeight:20-pause: { duration:10m } # 20% for 10 minutes-analysis:templates:-templateName:canary-success-rate-setWeight:50-pause: { duration:10m } # 50% for 10 minutes-setWeight:80-pause: { duration:5m } # 80% for 5 minutes# 100% happens automatically after final step# Auto-rollback on failureabortScaleDownDelaySeconds:30dynamicStableScale:true# Traffic management via IstiotrafficRouting:istio:virtualServices:-name:payment-service-vsvcroutes:-primarydestinationRule:name:payment-service-destrulecanarySubsetName:canarystableSubsetName:stable# Analysis template for canary healthanalysis:templates:-templateName:canary-success-ratestartingStep:2args:-name:service-namevalue:payment-servicetemplate:metadata:labels:app:payment-servicespec:containers:-name:payment-serviceimage:registry.example.com/payment-service:v2.3.1ports:-containerPort:8080readinessProbe:httpGet:path:/healthzport:8080initialDelaySeconds:5periodSeconds:10resources:requests:cpu:250mmemory:256Milimits:cpu:500mmemory:512Mi---# Analysis template -- Prometheus-based success rate checkapiVersion:argoproj.io/v1alpha1kind:AnalysisTemplatemetadata:name:canary-success-ratespec:args:-name:service-namemetrics:-name:success-rateinterval:60scount:5successCondition:result[0]>=0.99failureLimit:2provider:prometheus:address:http://prometheus.monitoring:9090query:|
sum(rate(http_requests_total{
service="{{args.service-name}}",
status=~"2..",
canary="true"
}[2m])) /
sum(rate(http_requests_total{
service="{{args.service-name}}",
canary="true"
}[2m]))
-name:p99-latencyinterval:60scount:5successCondition:result[0]<=500failureLimit:2provider:prometheus:address:http://prometheus.monitoring:9090query:|
histogram_quantile(0.99,
sum(rate(http_request_duration_ms_bucket{
service="{{args.service-name}}",
canary="true"
}[2m])) by (le)
)
Database migrations during releases require special care because they cannot be rolled back as easily as code.
Migration Type
Risk Level
Rollback Strategy
Requires Downtime
Add column (nullable)
Low
Drop column
No
Add column (NOT NULL + default)
Medium
Drop column
No (with care)
Drop column
High
Cannot undo
No (expand-contract)
Rename column
High
Cannot undo easily
No (expand-contract)
Add index
Medium
Drop index
No (CONCURRENTLY)
Change column type
High
Revert type
Sometimes
Add table
Low
Drop table
No
Drop table
Critical
Restore from backup
No
Expand-Contract Migration Pattern
-- Phase 1: EXPAND (deploy with old code still running)-- Add new column alongside old oneALTER TABLE users ADDCOLUMN email_normalized VARCHAR(255);
-- Backfill data (run as background job, not in migration)UPDATE users SET email_normalized =LOWER(TRIM(email))
WHERE email_normalized ISNULL
LIMIT 10000; -- Batch to avoid locking-- Phase 2: MIGRATE (deploy new code that writes to both columns)-- Application writes to BOTH email and email_normalized-- Application reads from email_normalized with fallback to email-- Phase 3: CONTRACT (after all code uses new column)-- Only after verifying no code reads the old columnALTER TABLE users DROPCOLUMN email;
ALTER TABLE users RENAME COLUMN email_normalized TO email;
Migration Runner with Safety Checks
#!/usr/bin/env bash# migrate.sh -- Safe migration runner with pre-flight checksset -euo pipefail
DB_NAME="${DB_NAME:?DB_NAME required}"
MIGRATION_DIR="${MIGRATION_DIR:-./migrations}"
DRY_RUN="${DRY_RUN:-false}"# Pre-flight checkspreflight_check() {
echo"=== Pre-flight checks ==="# 1. Check for pending transactions that could block
BLOCKED=$(psql -d "$DB_NAME" -t -c \
"SELECT count(*) FROM pg_stat_activity
WHERE state = 'idle in transaction'
AND query_start < now() - interval '5 minutes';")
if [ "$BLOCKED" -gt 0 ]; thenecho"ERROR: $BLOCKED long-running idle transactions detected"echo"These may block DDL operations. Investigate before proceeding."exit 1
fi# 2. Check disk space (migrations can temporarily double table size)
DISK_FREE=$(df -BG /var/lib/postgresql | tail -1 | awk '{print $4}' | tr -d 'G')
if [ "$DISK_FREE" -lt 20 ]; thenecho"ERROR: Only ${DISK_FREE}GB free. Migrations may need more space."exit 1
fi# 3. Verify backup is recent (within last hour)
LAST_BACKUP=$(psql -d -t -c \
2>/dev/null || )
}
() {
migration /*.sql;
MIGRATION_NAME=$( )
APPLIED=$(psql -d -t -c \
)
[ -gt 0 ];
[ = ];
-20
psql -d \
-v ON_ERROR_STOP=1 \
-c \
-f
psql -d -c \
}
preflight_check
run_migrations
A release train ships on a fixed cadence regardless of what features are ready. Features that miss the train wait for the next one.
Cadence Options
Cadence
Suitable For
Trade-offs
Daily
SaaS, internal tools
Fast feedback, high automation needed
Weekly
B2B products
Balanced pace, manageable testing
Bi-weekly
Regulated industries
More testing time, slower delivery
Monthly
Enterprise, on-prem
Maximum stability, slow feedback
Weekly Release Train Example
Monday | Feature freeze for this week's release
Code complete -- all PRs merged to release branch
Automated regression suite runs
Tuesday | QA validation day
Manual exploratory testing on staging
Performance benchmarks compared to baseline
Wednesday | Release candidate tagged (e.g., v2.4.0-rc.1)
Deploy to pre-production / canary
Stakeholder sign-off window opens
Thursday | Production deploy (canary -> full rollout)
Monitoring period (4 hours minimum)
Incident response team on standby
Friday | Retrospective and metrics review
Hotfix window (if needed)
No new releases on Friday afternoon