CI/CD is the automation that lets teams ship code many times a day instead of once a quarter — safely. It replaces the error-prone ritual of manual builds and hand-deployed servers with a pipeline that builds, tests, and releases on every change. The payoff isn't just speed: smaller, more frequent releases are less risky, because each carries fewer changes and is easier to reverse. It pairs naturally with containers (the artifact) and Kubernetes (the deploy target).
- CI = Continuous Integration — merge to main often and run an automated build + test on every commit, catching breakage immediately.
- CD = Continuous Delivery (always deployable, release on a button) or Continuous Deployment (every green build auto-ships to prod).
- Build once, promote the same artifact — an immutable image moves through dev → staging → prod unchanged, so you test exactly what you ship.
- The pipeline is staged with gates — source → build → test → security scan → deploy, each a gate that must pass.
- Deployment strategies limit blast radius — rolling, blue-green, and canary trade speed/cost for safety.
- Fast rollback is the safety net — immutable artifacts make reverting a tag switch, not a rebuild.
Continuous Integration runs an automated build and test suite on every commit so problems surface early. Continuous Delivery keeps every green build deployable; Continuous Deployment ships it automatically. The pipeline builds an immutable artifact once and promotes that same artifact through environments behind quality gates. Release safely with rolling/blue-green/canary strategies, and keep rollback to a single fast step. Smaller, more frequent releases are safer than big-bang ones.
Why CI/CD
Manual releases fail for predictable reasons: integration is painful when branches diverge for weeks, builds differ between machines, and a human running deploy steps at midnight makes mistakes. Automating the path from commit to production makes releases repeatable, fast, and reversible. The deeper insight is counterintuitive but well-established: deploying more often reduces risk, because each deploy contains a small, understandable change and a problem is easy to trace and undo — the opposite of a quarterly release with thousands of changes.
Continuous Integration
CI is the practice of integrating everyone's work into a shared mainline frequently — ideally many times a day — with an automated build and test suite running on every push. The point is to catch integration problems and regressions within minutes of the commit that caused them, while the change is fresh in the author's mind, rather than discovering a tangle of conflicts during a big merge weeks later. CI depends on a solid, fast, reliable test suite; without it, a "green" pipeline means nothing.
The Pipeline Stages
A CI/CD pipeline is a sequence of stages, each a gate that must pass before the next runs:
commit ─▶ [ source ] ─▶ [ build ] ─▶ [ test ] ─▶ [ scan ] ─▶ [ deploy ]
│ │ │ │
compile + unit + security/ rolling /
build image integration lint/SAST canary
│ │ │ │
└── any stage fails → stop, notify ───┘
build ONCE → produce artifact (e.g. image:sha) → promote it forward
Tools like GitHub Actions, GitLab CI, Jenkins, and CircleCI define these stages declaratively (usually in a YAML file in the repo). The pipeline runs automatically on triggers — a push, a pull request, a merge to main, or a tag.
Continuous Delivery vs Continuous Deployment
"CD" is two related-but-distinct ideas, and the distinction is a classic interview point:
| Aspect | Continuous Delivery | Continuous Deployment |
|---|---|---|
| End state | Every build is deployable | Every green build is deployed |
| To production | Manual approval (a button) | Fully automatic, no human |
| Use when | You want a human/business gate | You trust your tests fully |
Both require the same disciplined pipeline; the only difference is whether a human presses "release." Continuous Deployment is the more advanced end state and demands very high confidence in automated testing.
Build Once, Promote the Same Artifact
A foundational principle: build the artifact once and promote that identical artifact through every environment. If you rebuild for staging and again for prod, you're shipping something you never tested. With containers this is natural — the pipeline builds myapp:<git-sha>, runs tests against it, and the very same immutable image is what reaches production. The artifact is versioned and immutable, which is also what makes rollback trivial.
Deployment Strategies
How you replace the running version controls the blast radius of a bad deploy:
rolling : replace instances a few at a time v1 v1 v1 → v2 v1 v1 → v2 v2 v2
blue-green: stand up full v2 ("green"), flip traffic, keep v1 ("blue") to revert
canary : send 1% → 5% → 50% → 100% of traffic to v2, watching metrics
| Strategy | How | Trade-off |
|---|---|---|
| Rolling | Replace instances gradually | No extra capacity; mixed versions briefly; slower rollback |
| Blue-green | Full parallel env, flip traffic | Instant cutover & rollback; doubles infra during deploy |
| Canary | Shift a small % first, watch | Smallest blast radius; needs good metrics + automation |
Canary is the safest for high-stakes services because a bad release only hits a sliver of users before automated monitoring catches it and halts the rollout — which is why it pairs tightly with observability.
Rollback
The single most important safety property is being able to get back to a known-good state fast. Because artifacts are immutable and versioned, rollback is usually just "redeploy the previous image tag" — seconds, not a rebuild. Blue-green makes it a traffic flip; canary makes it "stop the rollout." The corollary: a deploy you can't quickly roll back is a deploy you shouldn't make. (Database migrations are the exception that needs care — make schema changes backward-compatible so old and new code can coexist during the transition; see encoding & evolution.)
Quality Gates and Practices
- Automated tests — unit, integration, end-to-end — the backbone; the pipeline is only as trustworthy as them.
- Static analysis & security scans — linting, SAST, dependency/CVE and image scanning fail the build on issues.
- Approvals — a manual gate before prod for delivery (or for sensitive changes).
- Trunk-based development — short-lived branches merged frequently keep integration cheap.
- Feature flags — decouple deploy from release: ship code dark, then turn it on (or off) without a redeploy.
Pitfalls
- Flaky tests — non-deterministic failures erode trust until people ignore red builds; quarantine and fix them.
- Slow pipelines — if CI takes an hour, people batch changes and stop integrating often; parallelize and cache.
- Snowflake environments — staging that differs from prod hides bugs; use the same images and infra-as-code.
- No rollback plan — especially around irreversible migrations; always have a tested way back.
CI/CD turns shipping into a repeatable, automated, reversible pipeline: integrate and test on every commit, build an immutable artifact once and promote it, and release with a strategy (rolling/blue-green/canary) that limits blast radius — with fast rollback as the safety net. The cultural payoff is that small, frequent deploys are safer than rare big ones.
CI vs CD? CI = automated build+test on every commit to catch breakage early; CD = Continuous Delivery (always deployable, manual release) or Continuous Deployment (auto-ship every green build).
Why build the artifact once? Promoting the same immutable artifact through environments means you ship exactly what you tested; rebuilding per environment risks drift.
Rolling vs blue-green vs canary? Rolling replaces gradually (no extra capacity); blue-green flips between two full environments (instant rollback, double infra); canary shifts a small % first while watching metrics (smallest blast radius).
How do you roll back fast? Redeploy the previous immutable artifact/tag (or flip traffic). Make DB migrations backward-compatible so code versions can coexist.
Deploy vs release? Feature flags separate them — deploy code dark, then enable the feature without another deploy.