|$ curl https://forge-ai.dev/api/markdown?path=docs/ci/continuous-deployment
$cat docs/continuous-deployment.md
updated Recently·28 min read·published

Continuous Deployment

CI/CDDeploymentIntermediate
Introduction

Continuous Deployment (CD) extends Continuous Integration by automatically deploying every change that passes the CI pipeline to production — without manual intervention. While Continuous Delivery stops at a deployable artifact, Continuous Deployment pushes that artifact live.

CD requires deep confidence in your test suite, robust rollback mechanisms, and deployment strategies that minimize risk. This guide covers the strategies, environments, and tooling needed to deploy safely and frequently.

Auto-Deploy Strategies

The core of CD is the pipeline that takes code from merge to production. Here is a typical automated deployment pipeline:

deploy-production.yml
YAML
1# GitHub Actions — Auto-Deploy to Production
2name: Deploy Production
3on:
4 push:
5 branches: [main]
6
7jobs:
8 deploy:
9 runs-on: ubuntu-latest
10 environment: production
11 steps:
12 - uses: actions/checkout@v4
13 - uses: actions/setup-node@v4
14 with:
15 node-version: 20
16 cache: npm
17 - run: npm ci
18 - run: npm run build
19
20 - name: Deploy to Vercel
21 uses: amondnet/vercel-action@v25
22 with:
23 vercel-token: ${{ secrets.VERCEL_TOKEN }}
24 vercel-org-id: ${{ secrets.ORG_ID}}
25 vercel-project-id: ${{ secrets.PROJECT_ID}}
26 vercel-args: --prod
27
28 - name: Run Smoke Tests
29 run: |
30 curl -f https://example.com/api/health
31 curl -f https://example.com
32
33 - name: Notify Team
34 uses: slackapi/slack-github-action@v1
35 with:
36 payload: |
37 { "text": "Deployed main to production ✅" }

info

Always run smoke tests against the deployed environment before marking a deployment as successful. A build can succeed but the deployed app can still fail due to environment configuration differences.
Preview & Staging Deployments

Preview deployments create ephemeral environments for every pull request, allowing reviewers to test changes in a production-like setting before merging.

FeatureVercel PreviewNetlify Deploy Preview
URL Patternproject-[hash].vercel.app[hash]--project.netlify.app
Auto-CreatedOn every PR pushOn every PR push
Environment VariablesSeparate preview env varsDeploy context env vars
Password ProtectionBasic auth or Vercel PasswordBasic auth
TeardownAuto on branch deleteAuto on PR close
vercel-preview.sh
Bash
1# Trigger Vercel Preview from CLI
2vercel --prebuilt
3
4# Deploy to a specific environment
5vercel --environment preview
6
7# List all preview deployments
8vercel list
9
10# Alias a preview URL for testing
11vercel alias set https://project-hash.vercel.app staging.example.com
Deployment Environments

A mature CD pipeline promotes code through multiple environments, each with increasing confidence requirements:

EnvironmentTriggerGateData
DevelopmentCode pushNoneMocked / local
PreviewPR createdCI passesSandbox / staging DB
StagingMerge to mainCode review + CIAnonymized production snapshot
ProductionDeploy triggerManual approval + smoke testsReal user data

best practice

Staging should be as close to production as possible — same infrastructure, same configuration, and real-ish data. The more staging differs from production, the less confidence you can have in your deployment pipeline. Use infrastructure-as-code to keep environments consistent.
Rollback Strategies

Every deployment must have a rollback plan. The best rollback is the one you never need, but when things go wrong, speed matters.

Vercel Instant Rollback

Vercel keeps deployment history. Rollback is a one-click operation that redeploys a previous build.

vercel-rollback.sh
Bash
1# List deployment history
2vercel list --all
3
4# Rollback to a specific deployment
5vercel rollback <deployment-url-or-id>
6
7# Rollback to the previous production deployment
8vercel rollback --confirm

Git-Based Rollback

For self-hosted deployments, revert the commit and redeploy the previous version.

git-rollback.sh
Bash
1# Revert to the previous commit
2git revert HEAD --no-edit
3git push origin main
4
5# Or checkout a known-good tag
6git checkout tags/v1.2.3
7npm run build
8npm run deploy

danger

Never roll back a database migration by reverting the code alone. If your deployment includes schema changes, the rollback must also reverse those changes. Always deploy database migrations separately from application code when possible.
Blue-Green vs. Canary Deployments

Blue-Green Deployment

Two identical environments (Blue and Green) run side by side. At any time, one serves production traffic. The new version is deployed to the inactive environment, then traffic is switched instantaneously.

blue-green.sh
Bash
1# Blue = current live (v1)
2# Green = new version (v2)
3
4# 1. Deploy v2 to Green environment
5kubectl apply -f deployment-v2.yaml --namespace=green
6
7# 2. Run smoke tests against Green
8curl -f https://green.internal.example.com/health
9
10# 3. Switch load balancer to Green
11kubectl patch service app -p '{"spec":{"selector":{"version":"v2"}}}'
12
13# 4. Monitor for errors. If issues:
14kubectl patch service app -p '{"spec":{"selector":{"version":"v1"}}}'
🔥

pro tip

Blue-green deployments enable instant rollback — just flip the load balancer back to the previous environment. The tradeoff is double the infrastructure cost during the transition window.

Canary Deployment

The new version is gradually rolled out to a small subset of users (the canaries) before expanding to 100%. Traffic shifting is controlled by a load balancer or feature flag.

canary-istio.yaml
YAML
1# Istio VirtualService for canary routing
2apiVersion: networking.istio.io/v1beta1
3kind: VirtualService
4metadata:
5 name: app-canary
6spec:
7 hosts:
8 - app.example.com
9 http:
10 - match:
11 - headers:
12 x-canary: "true"
13 route:
14 - destination:
15 host: app
16 subset: v2
17 - route:
18 - destination:
19 host: app
20 subset: v1
21 weight: 95
22 - destination:
23 host: app
24 subset: v2
25 weight: 5

warning

Canary deployments require robust observability. You need real-time metrics on error rates, latency, and user-facing errors to detect problems during the rollout. Without monitoring, you are flying blind — use metrics-based automated rollback triggers.
Feature Flags

Feature flags (toggles) decouple deployment from release. Code can be deployed to production but remain hidden behind a flag, enabling trunk-based development and gradual rollouts.

feature-flags.ts
TypeScript
1// LaunchDarkly or Flagsmith flag evaluation
2import { useFlags } from '@launchdarkly/react-client-sdk';
3
4function NewCheckoutFlow() {
5 const { newCheckout } = useFlags();
6
7 if (!newCheckout) {
8 return <LegacyCheckout />;
9 }
10
11 return <ModernCheckout />;
12}
13
14// Server-side flag evaluation
15const ldClient = LaunchDarkly.init(LAUNCHDARKLY_SDK_KEY);
16
17async function handler(req, res) {
18 const user = { key: req.user.id, email: req.user.email };
19 const showFeature = await ldClient.variation(
20 "new-checkout-flow",
21 user,
22 false // default value
23 );
24
25 if (showFeature) {
26 return renderNewCheckout(res);
27 }
28 return renderLegacyCheckout(res);
29}

best practice

Use feature flags for: gradual rollouts (1%, 10%, 50%, 100%), kill switches for disabling problematic features instantly, A/B testing, and environment-specific behavior. Avoid long-lived feature flags — clean them up after the feature is fully rolled out to prevent technical debt.
CD Best Practices
Deploy frequently — small releases are easier to debug and roll back than large batched releases.
Automate everything except the final production gate (if required by compliance). Manual steps introduce inconsistency.
Use deployment tags and changelogs to track exactly what code is running in each environment.
Run smoke tests after every deployment before routing production traffic.
Implement automatic rollback triggers based on error rate spikes (e.g., 5xx rate > 1%).
Keep database migrations backward-compatible with the current and previous versions of the application.
Use a deployment dashboard to visualize the state of all environments at a glance.
Practice incident drills: intentionally deploy a breaking change to staging and practice the rollback.
$Blueprint — Engineering Documentation·Section ID: CD-01·Revision: 1.0