| name | deployment-strategies |
| description | Guides expert-level deployment strategies implementation: ci-cd and best-practices decision frameworks, production-ready patterns, and concrete templates for deployment strategies workflows.
Use when the user asks about deployment strategies, deployment strategies configuration, or ci-cd best practices for deployment projects.
Do NOT use when the user needs a different devops cloud capability -- check sibling skills in the devops cloud subcategory.
|
| license | Apache-2.0 |
| metadata | {"author":"foundry-skills","version":"1.0.0","tags":"ci-cd devops best-practices","category":"devops-cloud","subcategory":"devops-cloud","depends":"","disclaimer":"none","difficulty":"intermediate"} |
Deployment Strategies
When to Use
Use this skill when:
- User asks which deployment strategy (blue/green, canary, rolling, recreate, A/B, shadow) fits their application and infrastructure
- User needs to implement or improve a zero-downtime deployment pipeline for a production service
- User wants to reduce deployment risk for a high-traffic or business-critical application
- User is debugging a failed deployment and needs to understand rollback procedures and blast radius containment
- User is designing a CI/CD pipeline and needs to choose a deployment pattern that matches their SLO (e.g., <0.1% error rate, <200ms p99 latency)
- User wants to implement progressive delivery -- feature flags, canary releases, or traffic splitting with automated promotion criteria
- User needs to understand the infrastructure prerequisites for a specific strategy (e.g., load balancer requirements for blue/green, service mesh for canary)
- User is migrating from a legacy deploy-and-pray approach to a modern, observable deployment workflow
Do NOT use this skill when:
- User needs infrastructure-as-code authoring (Terraform, Pulumi) -- use the infrastructure-as-code skill
- User needs container orchestration configuration (Kubernetes manifests, Helm charts) beyond what is required to implement a deployment strategy -- use the kubernetes-configuration skill
- User is asking about CI pipeline construction (build steps, test stages, artifact management) without a deployment context -- use the ci-pipeline-design skill
- User needs secrets management or vault configuration as a standalone topic -- use the secrets-management skill
- User is asking about database migration strategies as a standalone concern -- use the database-migration skill
- User needs general monitoring or observability setup -- use the observability-stack skill
- User is asking about incident response after a deployment is already failing in production -- use the incident-response skill
Process
1. Characterize the Application and Traffic Profile
Before recommending any strategy, gather these concrete facts:
- Traffic volume: Requests per second (RPS) at peak. A service handling 50 RPS tolerates more disruption than one at 50,000 RPS. Strategies that require traffic draining (blue/green) need 30--120 seconds of overlap capacity.
- Deployment frequency: Teams deploying once a week can tolerate heavier-weight strategies (blue/green with full environment provisioning). Teams deploying 20+ times per day need lightweight, automated strategies (rolling or canary with automated promotion).
- Session stickiness requirements: Stateful applications (WebSocket connections, server-side sessions) cannot survive mid-session instance replacement. Identify whether sessions can be externalized (Redis session store, JWT tokens) before choosing a strategy.
- Database migration coupling: Does this deploy include schema changes? If yes, the deployment strategy must be backward-compatible migration aware. Blue/green cannot be used naively with breaking schema changes -- the old environment will fail if it shares a database with the new schema.
- SLO targets: Note the specific error budget. If SLO is 99.9% availability (8.7 hours downtime/year), even a 2-minute outage consumes 1.4% of the annual budget. This often rules out the Recreate strategy for production.
- Rollback time objective (RTO): Ask: "How quickly must you be able to roll back?" Blue/green achieves <30 seconds. Rolling rollbacks take minutes proportional to replica count. This is the single most important differentiator between strategies.
2. Apply the Deployment Strategy Decision Framework
Use this decision tree in order:
-
Step 2a -- Can the environment sustain duplicate infrastructure cost?
- Yes (cloud, auto-scaling, sufficient budget): Blue/green is viable. Proceed to 2b.
- No (fixed hardware, cost-constrained, bare metal): Rolling or Canary are the primary options.
-
Step 2b -- Is near-instant rollback (<60 seconds) a hard requirement?
- Yes: Blue/green is the strongest choice. DNS or load balancer flip achieves it.
- No: Canary or rolling with automated rollback gates provides sufficient safety at lower cost.
-
Step 2c -- Is this a user-facing service where you need behavioral validation before full rollout?
- Yes, and you can instrument user metrics (conversion rate, error rate per segment): Canary with automated promotion criteria.
- Yes, but behavioral metrics are hard to define: Blue/green with manual validation gate.
- No (internal service, batch job, worker): Rolling with health check gates.
-
Step 2d -- Is downtime acceptable? (Scheduled maintenance window, internal tooling, non-production)
- Yes: Recreate strategy -- simplest possible. Stop old, start new.
- No: Eliminate Recreate from consideration.
-
Step 2e -- Do you need to test with real production traffic without user impact?
- Yes: Shadow deployment (traffic mirroring). Run the new version alongside production, mirror real traffic to it, compare responses. Zero user impact, highest fidelity testing.
3. Define Automated Promotion and Rollback Criteria
Every deployment strategy must have explicit, metric-based gates -- not manual approval for routine deploys:
- Error rate gate: HTTP 5xx rate >1% of requests over a 5-minute window triggers automatic rollback. Tune the threshold based on baseline error rate (never tighter than 3x the p99 baseline variance).
- Latency gate: p99 latency increase of >20% relative to the previous 30-minute baseline triggers rollback. Use relative thresholds, not absolute, to account for traffic-dependent variance.
- Saturation gate: CPU >80% sustained for 3 minutes or memory >90% triggers rollback. These indicate the new version may degrade under load.
- Business metric gate (canary-specific): For canary, define a primary business metric: add-to-cart rate, checkout completion, API success rate. A >5% relative degradation compared to the stable cohort triggers automatic rollback.
- Soak time: Define minimum time at each canary stage (e.g., 10% traffic for 10 minutes, 25% for 15 minutes, 50% for 20 minutes) before automatic promotion. Even if metrics look good, statistical significance requires time.
- Canary stages: Do not jump from 0% to 100%. Use stages: 1%, 5%, 10%, 25%, 50%, 100%. Each stage doubles (approximately) exposure while keeping blast radius bounded.
4. Design the Infrastructure Prerequisites
Each strategy has specific infrastructure requirements -- confirm these before implementation:
5. Implement the Deployment Pipeline
Translate the chosen strategy into pipeline stages:
6. Implement Rollback Procedures
Rollback must be defined before deploy begins, not after something goes wrong:
- Blue/green rollback: Flip the load balancer target group back to blue. Execution time: <30 seconds. This is the "undo button" -- it requires no artifact rebuild, no re-deploy.
- Rolling rollback:
kubectl rollout undo deployment/<name> or pipeline trigger that re-deploys the previous artifact tag. Time proportional to replica count -- 10 replicas at 2 replicas/minute = 5 minutes.
- Canary rollback: Remove the canary Deployment and route 100% traffic back to stable. If using Argo Rollouts,
kubectl argo rollouts abort <name>.
- Database rollback coupling: If the deploy included a migration, and the migration is not backward-compatible, the database CANNOT be rolled back alongside the application without data loss. This is the most common reason zero-downtime deployments fail. Enforce the expand-contract pattern: never deploy a breaking schema change and application change simultaneously.
- Artifact immutability: Tag all artifacts with immutable identifiers (Git SHA, not
latest). latest tags make rollback ambiguous and unreliable.
7. Instrument and Close the Feedback Loop
A deployment strategy without observability is a guess:
- DORA metrics: Track Deployment Frequency, Lead Time for Changes, Change Failure Rate, and Mean Time to Recovery. These four metrics objectively measure deployment strategy effectiveness. Target elite performance: deploy frequency daily or more, lead time <1 day, change failure rate <5%, MTTR <1 hour.
- Deployment annotations: Push a deployment event annotation to your metrics platform every time a deploy occurs. This allows instant visual correlation between deploys and metric changes in dashboards.
- Version tagging: Every metric emitted by your application must carry a version label. This enables side-by-side comparison of canary vs. stable error rates in Prometheus or Datadog.
- Runbook linkage: Every automated alert must link to a runbook that explains how to respond. Deployment-related alerts (e.g., "canary error rate elevated") must include the rollback command in the runbook body.
- Post-deploy review cadence: After every deployment incident (not just P1s), conduct a 30-minute blameless postmortem. Track whether the deployment strategy's automated gates caught the problem or missed it. Use this to tune gate thresholds.
Output Format
When advising on or designing a deployment strategy, produce the following artifacts:
Strategy Selection Summary
Application: [service name]
Team size: [N engineers]
Deploy frequency: [N per day/week]
Traffic profile: [peak RPS, p99 latency SLO]
Availability SLO: [99.X%]
Rollback RTO: [< N seconds/minutes]
Recommended strategy: [Blue/Green | Canary | Rolling | Recreate | Shadow]
Rationale: [2-3 sentences citing the specific factors above]
Ruled out: [Strategy X -- reason; Strategy Y -- reason]
Deployment Gate Configuration
gates:
error_rate:
threshold: 1.0%
window: 5m
action: rollback
latency_p99:
threshold: +20%
window: 5m
action: rollback
cpu_saturation:
threshold: 80%
sustained_for: 3m
action: rollback
soak_time_minimum:
per_stage: 10m
action: hold_until_elapsed
canary_stages:
- weight: 1
soak: 10m
- weight: 5
soak: 10m
- weight: 10
soak: 15m
- weight: 25
soak: 15m
-
Rolling Update Configuration (Kubernetes example)
apiVersion: apps/v1
kind: Deployment
metadata:
name: [service-name]
annotations:
deployment.kubernetes.io/change-cause: "[git-sha] [ticket-id] [brief description]"
spec:
replicas: 6
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 0
maxSurge: 2
minReadySeconds: 30
template:
spec:
containers:
- name: [service-name]
image: [registry]/[service]:[git-sha]
readinessProbe:
httpGet:
path: /health/ready
port: 8080
initialDelaySeconds: 15
periodSeconds: 5
failureThreshold: 3
successThreshold: 1
Blue/Green Pipeline Pseudocode
PIPELINE blue_green_deploy(artifact_tag):
1. PROVISION green environment
- Clone blue infrastructure (IaC parameterized by slot name)
- Apply artifact_tag to green deployment
- Wait for all green replicas to pass readiness probes
2. VALIDATE green (internal traffic only)
- Run integration test suite against green internal endpoint
- Run synthetic transactions against green
- Assert: error rate < 0.5%, p99 latency < SLO threshold
IF validation fails:
DESTROY green environment
FAIL pipeline with validation report
3. SHIFT traffic
- Update load balancer: 100% -> green
- Record rollback point: blue slot, load balancer previous config
4. OBSERVE (15 minute soak)
- Poll error rate, latency, saturation every 30 seconds
IF any gate breached:
ROLLBACK: update load balancer 100% -> blue
ALERT on-call with rollback reason and metrics
FAIL pipeline
5. PROMOTE
- Keep blue environment for 2 hours (fast rollback window)
- After 2 hours: DESTROY blue or re-tag as next deploy slot
- ANNOTATE metrics platform with deploy event
6. POST-DEPLOY
- Verify synthetic transactions passing
- Confirm no alerts fired
- Mark deployment as successful in deployment tracking system
Decision Matrix
| Factor | Recreate | Rolling | Blue/Green | Canary | Shadow |
|---|
| Downtime | Full | Near-zero | Zero | Zero | Zero |
| Rollback speed | Minutes (redeploy) | 3--15 min | <30 sec | <2 min | N/A |
| Infrastructure cost | 1x | 1x--1.25x | 2x | 1x--1.25x | 2x |
| Blast radius | 100% | Staged | 100% then flip | 1%--100% staged | 0% (shadow only) |
| DB migration safety | Simple | Moderate | Complex (shared DB) | Best (staged) | Read-only test |
| Implementation complexity | Low | Low--Medium | Medium | Medium--High | High |
| Best for | Dev/test, batch | General purpose | Stateless, critical | User-facing, risk-averse | Validation before canary |
Rules
-
NEVER use :latest as an artifact tag in any deployment. Latest is mutable -- you cannot reliably roll back to it because the tag may point to a different image by the time you attempt rollback. Always tag with the immutable Git SHA (12 characters minimum).
-
NEVER deploy a breaking database schema change in the same deployment as the application code that depends on it. Use the expand-contract pattern: Phase 1 -- add the new column (backward-compatible), deploy the app that can read both schemas. Phase 2 -- remove the old column after the new app version is fully deployed and validated.
-
NEVER configure maxUnavailable > 0 in a rolling update for a service with fewer than 4 replicas. With 2 replicas and maxUnavailable: 1, you are running at 50% capacity during the rollout. Set maxUnavailable: 0 and maxSurge: 1 for small replica counts.
-
NEVER set DNS TTL to 300 seconds and use DNS-based blue/green switching. At TTL 300, it takes up to 5 minutes for all clients to see the switch, and rollback is equally slow. Drop TTL to 60 seconds at least 10 minutes before the deploy window.
-
NEVER treat canary rollout by replica count as equivalent to canary rollout by traffic percentage. Two canary pods out of 10 total does not guarantee 20% of traffic goes to canary -- it depends on load balancer behavior, session affinity, and request distribution. Use explicit traffic weighting in your load balancer or service mesh.
-
ALWAYS define rollback criteria and the rollback command before the deployment pipeline runs. The rollback procedure must be documented, tested, and accessible to the on-call engineer in under 60 seconds. Never improvise rollback steps during an incident.
-
ALWAYS ensure the readiness probe endpoint performs a deep health check. A shallow readiness probe (HTTP 200 on /) that does not verify database connectivity will mark an instance as ready before it can actually serve traffic successfully, invalidating your deployment health gates.
-
NEVER skip the minimum soak time gate even when metrics look excellent. Statistical significance requires time. A canary error rate of 0% after 30 seconds on 1% traffic means nothing -- it may have received fewer than 10 requests. Enforce minimum soak times regardless of observed metrics.
-
ALWAYS keep the previous deployment artifact available for at least 2 hours after a successful blue/green promotion. Subtle bugs (memory leaks, cache poisoning, background job failures) often manifest 30--90 minutes after deployment. Keeping the blue environment live enables instant rollback without a rebuild.
Edge Cases
Stateful Applications and Session Affinity
Scenario: The application maintains server-side state (WebSocket connections, long-polling, sticky sessions) and cannot be dropped mid-session during a rolling update.
Handling:
- Configure load balancer sticky sessions (cookie-based affinity, not IP-based -- IP affinity breaks under NAT) before initiating the rollout.
- Set
terminationGracePeriodSeconds to at least the maximum expected session duration (for WebSockets, this may be 300--900 seconds).
- Configure the application to reject new connections gracefully during shutdown (
SIGTERM handler closes the accept loop, drains existing connections, then exits).
- For rolling updates,
maxUnavailable: 0 is mandatory -- never pull an instance while it may be holding active sessions.
- If session duration exceeds a reasonable termination grace period, externalize session state (Redis Cluster with TTL) before attempting any live rolling update strategy. This is a prerequisite, not an optimization.
Database Migration Coupled to Deployment
Scenario: A new application version requires schema changes (column rename, table restructure, index addition) that are incompatible with the running version.
Handling:
- Apply the expand-contract (also called parallel change) pattern across three sequential deployments:
- Expand: Add new schema elements (new column, new table) without removing old ones. Deploy application version that writes to both old and new schema simultaneously.
- Migrate: Run data migration to backfill new schema from old data. Application continues writing to both. Validate backfill completeness.
- Contract: Deploy application version that reads only new schema. Remove old schema elements.
- Each phase must be independently deployable and rollback-safe.
- For blue/green with a shared database: both blue and green must be compatible with the deployed schema simultaneously, since both may be serving traffic during validation.
- Never use
ON DELETE CASCADE or destructive migrations in the expand phase -- they cannot be rolled back.
High-Frequency Deployment (>20 Deploys Per Day)
Scenario: A team is deploying dozens of times per day, and heavyweight strategies (full blue/green environment provisioning) introduce unacceptable pipeline latency.
Handling:
- Use pre-warmed environment pools (one blue, one green always running) rather than on-demand provisioning. Provisioning a new environment from scratch takes 3--10 minutes; swapping a pre-warmed slot takes 30 seconds.
- Implement progressive delivery with feature flags as the primary risk-reduction mechanism, separate from the deployment event. The deployment ships the code (dark launch); the feature flag controls who sees it. This decouples deployment risk from feature risk.
- Use rolling updates with aggressive automated gates rather than blue/green for most services. Reserve blue/green for the highest-criticality services (payment processing, authentication) where rollback speed justifies 2x infrastructure cost.
- Cap pipeline cycle time: if a deploy pipeline takes >15 minutes, engineers will batch changes to reduce the overhead, which increases blast radius. Optimize pipeline stages (parallel test execution, layer-cached container builds) to stay under 10 minutes gate-to-production.
Multi-Region and Multi-Cluster Deployment
Scenario: The service runs across 3+ AWS regions or Kubernetes clusters, and a deployment must be coordinated across all of them.
Handling:
- Never deploy to all regions simultaneously. Use a progressive regional rollout: deploy to the lowest-traffic region first (often us-west-2 or a non-primary region), observe for 15--30 minutes, then proceed to additional regions.
- The primary (highest traffic) region should be the last region deployed. This limits blast radius to a fraction of global traffic during the most dangerous phase.
- Define a "region health gate" -- before promoting to the next region, confirm that the previous region's error rate, latency, and saturation are within bounds.
- Implement global rollback as a single operation via traffic weighting at the CDN or global load balancer layer (Cloudflare, AWS Global Accelerator). Do not rely on per-region rollbacks in a multi-region incident -- it takes too long.
- Version skew: during the rollout window, different regions run different versions. Ensure inter-service APIs are backward-compatible for at least 2 consecutive versions. Use semantic versioning for internal APIs and enforce compatibility contracts in CI.
Rollback Fails Due to Database State
Scenario: Automated rollback triggers during a canary deploy, but the new version has already written data in a format the old version cannot read.
Handling:
- This scenario indicates the expand-contract pattern was not followed. The root fix is procedural (enforce backward-compatible migrations), but the immediate handling is:
- Do NOT roll back the application if doing so would cause data corruption or application crashes in the old version.
- Instead, roll forward with a hotfix that restores read compatibility.
- Define this as an incident: the deploy gate failed to catch a data compatibility issue before rollback became unsafe.
- Add a pre-deploy check to the pipeline: query the running database schema version and assert compatibility with both the current and the new application version before the deploy proceeds.
- In the post-incident review, enforce the requirement that all schema migrations be reviewed by a database engineer and tested in a staging environment with production-scale data before merging.
Shadow Deployment Side Effects
Scenario: Shadow/mirroring deployment is used to test a new service version, but the shadow path triggers unintended side effects (emails sent, payments charged, messages published to queues).
Handling:
- Shadow deployments require a strict read-only contract for the mirrored path. The shadow service must never write to production databases, call external payment processors, send notifications, or publish to production message queues.
- Implement a shadow-mode flag in the application that, when enabled, replaces all write operations with no-ops or writes to a shadow-specific database.
- Alternatively, provide stub implementations of all side-effecting dependencies for the shadow environment: a stub payment service that accepts but does not process, a stub email service that logs but does not send.
- Verify the stub/no-op behavior in integration tests before enabling shadow traffic. A single missed write path in shadow mode can result in double-charged customers or duplicate notifications.
- Review shadow response body differences against production -- mismatches in response structure (not just latency/error rates) often reveal bugs that would have caused errors in production.
Canary Deployment on a Service with Low Traffic Volume
Scenario: A service handles 20 RPS peak. At 5% canary weight, only 1 request per second goes to the canary. Statistical significance for a 1% error rate requires hundreds of requests, meaning the soak time must be very long.
Handling:
- Adjust canary stages for low-traffic services: skip the 1% and 5% stages (too little traffic to be meaningful) and start at 10--20%.
- Extend soak times proportionally. For a service at 2 RPS canary traffic, achieving 500 requests requires 250 seconds (4.2 minutes). Set minimum soak time to at least 10 minutes at 10% to accumulate sufficient data.
- Use wider error rate confidence intervals for low-traffic gates. A single 500 error in 50 requests is 2% -- this should not trigger rollback on its own. Require at least 5 errors in the window, or use a Bayesian error rate model rather than a simple threshold.
- Consider using synthetic load (load test against canary) in addition to organic traffic to accelerate validation, especially for performance regression checks.
Example
Input: "We're running a payment processing API on Kubernetes (6 replicas). It handles about 800 RPS at peak, our SLO is 99.95% availability, and we deploy roughly 3--5 times per week. We've been doing rolling updates but had two incidents this year where a bad deploy took 8 minutes to roll back and degraded the service during that time. What deployment strategy should we use and how do we implement it?"
Output:
Analysis
The current situation reveals a specific problem: rolling update rollback takes 8 minutes, and during that window, degraded pods are serving traffic. For a payment API at 99.95% SLO (4.4 hours downtime budget/year), an 8-minute degradation event consumes 3% of the annual budget in a single incident.
The root cause with rolling rollbacks is that kubectl rollout undo re-deploys the previous image using the same rolling update mechanism -- it does not instantly revert traffic. With 6 replicas, even with maxSurge: 2, replacing all pods takes approximately 6--10 minutes.
Recommendation: Blue/Green for this service.
Ruled out:
- Rolling update -- current strategy. Rollback RTO of 6--10 minutes is incompatible with payment SLO. Ruled out.
- Canary -- suitable as a secondary risk gate, but canary rollback still takes 2--5 minutes. Payment processing needs faster rollback as the primary mechanism.
- Recreate -- requires full downtime. Payment API cannot have planned downtime. Ruled out completely.
Strategy Selection Summary
Application: payment-api
Team size: ~6 engineers (inferred)
Deploy frequency: 3--5 per week
Traffic profile: 800 RPS peak
Availability SLO: 99.95% (4.4 hours/year)
Rollback RTO: <60 seconds (required for payment criticality)
Recommended strategy: Blue/Green (primary) + Canary gates (pre-switch validation)
Rationale: Blue/green achieves sub-30-second rollback via load balancer
flip, which is the only mechanism meeting the 99.95% SLO at
800 RPS. Canary gates validate the green environment with 5%
of traffic before the full switch, catching regressions before
100% exposure.
Ruled out:
Rolling update -- 6--10 min rollback violates SLO budget
Canary (only) -- 2--5 min rollback still too slow for payment path
Recreate -- requires downtime, never appropriate for payment APIs
Infrastructure Changes Required
The current rolling update setup needs these additions:
-
Two persistent environment slots -- Maintain a "blue" and "green" Deployment in the same Kubernetes namespace, or use two separate namespaces. The load balancer (Kubernetes Service + Ingress, or an ALB) routes traffic to the active slot.
-
Traffic switching mechanism -- Use Kubernetes Service selector labels to switch traffic. The Service selects pods by label slot: blue or slot: green. Switching is instantaneous: one kubectl patch service payment-api -p '{"spec":{"selector":{"slot":"green"}}}' command.
-
Internal validation endpoint -- The green Deployment needs a separate internal Service (not exposed externally) for running integration tests against it before the traffic switch.
Deployment Gate Configuration
gates:
error_rate:
metric: 'rate(http_requests_total{status=~"5..",service="payment-api"}[5m]) /
rate(http_requests_total{service="payment-api"}[5m])'
threshold: 0.5%
window: 5m
action: rollback
latency_p99:
metric: 'histogram_quantile(0.99, rate(http_request_duration_seconds_bucket
{service="payment-api"}[5m]))'
threshold: +15%
window: 5m
action: rollback
payment_success_rate:
metric: 'rate(payment_transactions_total{status="success"}[5m]) /
rate(payment_transactions_total[5m])'
threshold: -2%
window: 5m
action: rollback
soak_time_pre_switch:
duration: 15m
action: hold_until_elapsed
canary_pre_validation_stages:
- weight:
Kubernetes Configuration
Blue and Green Deployments:
apiVersion: apps/v1
kind: Deployment
metadata:
name: payment-api-green
namespace: payments
annotations:
deployment.kubernetes.io/change-cause: "a3f92c1 PYMT-1042 fix retry idempotency"
spec:
replicas: 6
selector:
matchLabels:
app: payment-api
slot: green
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 0
maxSurge: 2
minReadySeconds: 30
template:
metadata:
labels:
app: payment-api
slot: green
version: "a3f92c1"
spec:
containers:
- name: payment-api
image: registry.example.com/payment-api:a3f92c1
ports:
Service (traffic switching mechanism):
apiVersion: v1
kind: Service
metadata:
name: payment-api
namespace: payments
spec:
selector:
app: payment-api
slot: blue
ports:
- port: 80
targetPort: 8080
type: ClusterIP
---
apiVersion: v1
kind: Service
metadata:
name: payment-api-green-internal
namespace: payments
spec:
selector:
app: payment-api
slot: green
ports:
- port: 80
targetPort: 8080
type: ClusterIP
Pipeline Steps
PIPELINE payment-api-blue-green-deploy(git_sha):
PRE-CHECKS (fail fast):
- Assert image registry.example.com/payment-api:[git_sha] exists and is signed
- Run db-migration-compatibility-check: assert migration is backward-compatible
with current running version
- Assert green slot Deployment does not already exist (clean slate)
STEP 1 -- Deploy green (5 min):
- Apply payment-api-green Deployment with image tag [git_sha]
- Wait: all 6 replicas pass readiness probes
- If timeout (10 min): destroy green, fail pipeline, page on-call
STEP 2 -- Internal integration tests against green (3 min):
- POST /payments/initiate against payment-api-green-internal Service
- Assert: 200 response, idempotency key handled correctly
- Assert: database write confirmed (read-back)
- Assert: no errors in green pod logs in last 60 seconds
- If any assertion fails: destroy green, fail pipeline
STEP 3 -- Canary pre-validation (15 min soak at 5%):
- Update Ingress: route 5% of traffic to green (Nginx split_clients or NGINX Plus)
- Start 15-minute observation timer
- Poll every 30s: error_rate, latency_p99, payment_success_rate
- If any gate breaches: route 100% back to blue, destroy green, fail pipeline
- If soak completes successfully: proceed
STEP 4 -- Full traffic switch (<30 seconds):
- kubectl patch service payment-api -n payments \
-p '{"spec":{"selector":{"slot":"green"}}}'
- Record rollback command: kubectl patch service payment-api -n payments \
-p '{"spec":{"selector":{"slot":"blue"}}}'
- Annotate Grafana, Datadog with deployment event: service=payment-api,
version=[git_sha], slot=green
STEP 5 -- Post-switch observation (15 min):
- Run synthetic transaction every 30 seconds: full payment flow end-to-end
- Poll all gates as in Step 3
- If any gate breaches: IMMEDIATE rollback (selector flip to blue), page on-call
- Rollback completes in <30 seconds
STEP 6 -- Promote and cleanup:
- Mark deploy as successful in deployment tracking
- Retain blue Deployment for 2 hours (fast rollback window)
- After 2 hours, if no rollback: delete blue Deployment, tag blue slot as next
deploy target
- Update PodDisruptionBudget selector to "green"
STEP 7 -- Post-deploy validation:
- Confirm DORA metrics updated: deployment frequency, lead time
- Verify no new alerts firing in PagerDuty
- Send deploy notification to #payments-deploys Slack channel with
rollback command embedded in message body
Expected Improvements
| Metric | Current (Rolling) | Target (Blue/Green) |
|---|
| Rollback time | 6--10 minutes | <30 seconds |
| Traffic impact during bad deploy | Full 100% degraded for 8 min | Max 5% for 15 min (canary phase) |
| SLO budget consumed per incident | ~3% of annual | ~0.06% of annual |
| Deploy pipeline duration | ~8 min | ~25 min (longer, but safer) |
| Time-to-detect bad deploy | When rollback starts | Within 30s of canary stage |
The 25-minute pipeline duration is the primary trade-off. For a payment API deploying 3--5 times per week, 25 minutes is acceptable. If pipeline duration becomes a blocker, the canary pre-validation stage (Step 3) can be parallelized with synthetic load to reduce the soak time while maintaining statistical significance.