KAHIBARO
Discord Login Register

24.3. Continuous Delivery

Understanding Continuous Delivery

Continuous Delivery, usually shortened to CD, is a software engineering practice where your code is always in a deployable state and can be released to users at any time with a small, repeatable, low‑risk process.

You will often see CI/CD used together. Continuous Integration (CI) focuses on merging and testing code frequently. Continuous Delivery (CD) focuses on making that tested code ready for production release at all times.

Core idea of Continuous Delivery:
Every change that passes automated tests is automatically prepared for release to production, and releasing it is a business decision, not a technical challenge.

In backend development, this is especially important because servers, databases, and APIs must be updated safely without downtime or data loss.


Continuous Delivery vs Continuous Deployment

These two terms are close but not the same.

PracticeWhat gets automatedWho decides to release?
Continuous IntegrationBuild and automated tests on each changeDeveloper merges when tests pass
Continuous DeliveryBuild, test, package, and prepare for releaseHuman (team, product owner, SRE)
Continuous DeploymentBuild, test, package, and auto release to prodSystem releases automatically

With Continuous Delivery:

With Continuous Deployment:

Important distinction:
Continuous Delivery automates up to production and requires manual approval.
Continuous Deployment automates through production with no manual gate.

In this course, you will mostly focus on Continuous Delivery, because it is a safer and more common initial step for backend teams.


Why Continuous Delivery Matters for Backend Developers

For backend services, manual and infrequent releases often cause:

Continuous Delivery aims to solve this by:

Some concrete benefits:

  1. Faster feedback
    You can deploy new backend endpoints or changes to staging quickly and test them with real clients or QA.
  2. Reduced risk
    Each deployment contains fewer changes. If something breaks, it is easier to find and fix.
  3. Easier rollbacks
    If each release is versioned and automated, rolling back often becomes a single command or button.
  4. Better collaboration
    Backend, frontend, QA, and product can all work against the same, frequently updated environments.

What Does “Always Deployable” Mean?

In Continuous Delivery, the main branch of your repository should always be:

This does not mean the application is perfect. It means that at any point, if the business asks for a release, you can:

  1. Take the current main commit.
  2. Trigger the release pipeline.
  3. Deploy to production safely.

Example in a Backend Context

Imagine a FastAPI application with a PostgreSQL database.

In a Continuous Delivery setup:

If all steps pass, the pipeline marks this version as ready for production.

You might then:

The Continuous Delivery Pipeline

A CD pipeline is a sequence of automated steps that move code from “just built” to “ready for production” and often beyond into “actually deployed”.

A typical backend Continuous Delivery pipeline might have these stages:

  1. Build
    • Install dependencies.
    • Run static checks (like linters or formatters).
    • Build a Docker image of your backend.
  2. Test
    • Run unit tests.
    • Run integration tests with a real database (like PostgreSQL in Docker).
    • Run API tests against the running backend.
  3. Package and Publish
    • Tag the build (for example, v1.4.3).
    • Push the Docker image to a container registry.
    • Save artifacts like migration scripts or documentation.
  4. Deploy to Staging
    • Deploy the new image to a staging environment.
    • Apply database migrations on staging.
    • Run smoke tests on staging (basic endpoints, health checks).
  5. Manual Approval
    • Developer, QA, or product reviews staging.
    • Someone clicks “approve” for production deployment.
  6. Deploy to Production
    • Deploy the same image and configuration used in staging to production.
    • Apply migrations (carefully, often with special strategies).
    • Run health checks.
  7. Post‑Deployment Checks
    • Monitor logs and metrics.
    • If something goes wrong, roll back.

Simple Pipeline Flow

You can think of a Continuous Delivery pipeline as a function:

$$
\text{Pipeline}(commit) \rightarrow \text{deployable version}
$$

Where a deployable version includes:

Key Practices that Enable Continuous Delivery

You cannot just “turn on” Continuous Delivery. You need some practices in place.

Automated Testing

Without automated tests, you cannot safely rely on a pipeline to tell you if code is good enough.

In backend development you typically need:

Rule:
If a bug is found after release, add or improve an automated test that would have caught it. Over time, your test suite becomes a safety net for Continuous Delivery.

Infrastructure as Code

Your environments should be created and updated via code:

This makes environments:

Configuration Management

Backend services often have environment-specific settings:

In Continuous Delivery, configuration must be:

You will cover this in more depth in the CI/CD and deployment chapters, but for CD it is essential.

Versioning and Artifacts

Every successful pipeline run should produce:

This lets you:

Continuous Delivery Across Environments

You will often have multiple environments:

EnvironmentPurposeWho uses it
DevDeveloper playground, often localIndividual developers
TestRun CI/CD tests, integration, performanceCI pipeline, QA
StagingProduction-like environment, final verificationQA, product, sometimes clients
ProdReal users and real dataCustomers, systems

In Continuous Delivery, the goal is:

Example: FastAPI Service Through Environments

  1. Code merged to main.
  2. CI builds my-api:1.0.5 Docker image, pushes it to a registry.
  3. CI deploys my-api:1.0.5 to test and runs automated tests.
  4. If successful, CI deploys my-api:1.0.5 to staging.
  5. After manual approval, CI deploys the same image my-api:1.0.5 to production.

This is safer than rebuilding for every environment, because you avoid “it worked on staging but the production build is different”.


Release Strategies in Continuous Delivery

How you actually switch traffic to new backend versions is also part of Continuous Delivery.

Common strategies:

1. Rolling Updates

2. Blue‑Green Deployments

3. Canary Releases

These strategies reduce risk and integrate well with Continuous Delivery pipelines.


Database Changes in Continuous Delivery

Backend deployments often include database schema changes. Handling these safely is critical.

Some common practices:

  1. Database Migrations as Code
    • Use tools like Alembic (for SQLAlchemy) to define migrations in version control.
    • Migrations run automatically in the pipeline or as part of deployment.
  2. Backward Compatible Changes
    • Try to make schema changes that work with both old and new code for some time.
    • For example:
      • Add a new column but do not remove the old one immediately.
      • Deploy code that writes to both columns.
      • Later deploy code that reads from the new column.
      • Finally, remove the old column.
  3. Safe Rollbacks
    • Consider what happens to data if you roll back the application but the database schema is newer.
    • Sometimes you need rollback migrations or clear steps to fix data.

Rule for database changes:
Assume application and database may be on slightly different versions during deployment. Migrations must not break older or newer versions unexpectedly.


Example: A Simple Continuous Delivery Workflow

Here is a simplified Continuous Delivery pipeline for a FastAPI + PostgreSQL project using Docker and GitHub Actions. This is not full YAML, but it gives a sense of the flow.

  1. On merge to main:
text
   1. Checkout code
   2. Set up Python
   3. Install dependencies
   4. Run linters and formatters
   5. Run unit tests
   6. Build Docker image: my-api:${GIT_SHA}
   7. Push Docker image to registry
   8. Run integration tests using that image in Docker Compose (FastAPI + Postgres)
   9. If all pass, deploy image to staging (for example via Docker Compose or Kubernetes)
   10. Run smoke tests against staging (health endpoint, one main endpoint, etc.)
   11. Mark build as "ready for production"
  1. On manual approval for production:
text
   1. Take same Docker image tag (my-api:${GIT_SHA})
   2. Update production environment to use this image
   3. Run database migrations
   4. Run health checks
   5. Notify team of deployment

No code changes happen between staging and production. Only configuration (like database URLs and secrets) differ.


Team Practices Around Continuous Delivery

Technology is only part of Continuous Delivery. Team habits matter a lot.

Helpful practices:

  1. Trunk‑based development
    • Developers merge small changes to main frequently.
    • Feature branches are short‑lived.
    • Avoid long‑running branches that diverge.
  2. Small, incremental changes
    • Avoid huge PRs that are hard to review and test.
    • Break features into small backend changes that can be deployed safely.
  3. Feature flags
    • Use configuration switches to turn features on or off.
    • You can deploy code for a feature that is disabled in production, then enable it later.
  4. Strict pipeline rules
    • If the pipeline is red (failing), fix it before adding new changes.
    • Do not bypass tests or manual approvals except in emergencies.
  5. Monitoring and observability
    • After each deployment, you should have:
      • Logs to inspect errors,
      • Metrics (like response times, error rate),
      • Health checks for services.

Challenges and How to Handle Them

Continuous Delivery is powerful but not trivial.

Typical challenges:

ChallengeMitigation idea
Flaky testsStabilize tests, isolate side effects, use fixed test data
Long pipelinesParallelize steps, optimize Docker builds and test suites
Complex manual stepsScript and automate them, use Infrastructure as Code
Risky database changesUse incremental migrations, test thoroughly in staging
Resistance to frequent deploymentsStart with non‑critical services, show reliability improvements

It is normal for a team to adopt Continuous Delivery gradually. You do not need perfection to start gaining value. Even automating build, tests, packaging, and staging deployment is already a big win.


How This Fits the Rest of the Course

In other parts of this course, you will:

Continuous Delivery is the conceptual goal that explains why we set up pipelines in a particular way. It is about ensuring that your backend can be released safely and quickly whenever needed.

Views: 8

Comments

Please login to add a comment.

Don't have an account? Register now!