Course contentsShow
← Docker, Kubernetes & CI/CD
Lesson 685 of 80210. Deployment Strategies and GitOpsFree lesson

Managing Database Schema Migrations During Updates

Implement backward-compatible database migration patterns that allow both old and new application versions to function simultaneously.

In this lesson, you will learn how to design database migrations that allow your application to remain stable even when running multiple versions concurrently during a rolling update.

When performing a rolling update or a canary release in Kubernetes, your cluster briefly hosts both the "old" and "new" versions of your application code. If the new version requires a database schema change, you cannot simply perform a destructive migration, as it would break the old application instances still handling live traffic.

The Expand-Contract Pattern

To maintain backward compatibility, we follow the Expand-Contract (or Parallel Change) pattern. This strategy breaks a single breaking migration into three distinct, non-breaking steps:

  1. Expand: Modify the database in a way that is additive. For example, if you are renaming a column, you first add the new column while keeping the old one. Your application code is updated to write to both columns (or double-write) but continues to read from the old one.
  2. Migrate: Backfill the new column with existing data from the old column.
  3. Contract: Once the new version is fully deployed and verified, you update the application to read from the new column and eventually drop the old column in a subsequent deployment.

Implementing in Kubernetes

In a CI/CD pipeline, these migrations are often executed as a Job or InitContainer before the rollout begins. Because the migration must support both versions, the SQL should be purely additive:

-- Migration Step: Expand
ALTER TABLE users ADD COLUMN full_name VARCHAR(255);
-- No columns are deleted yet, ensuring the 'old' binary still functions.

If your application needs to handle a rename, ensure your migration logic checks for column existence before executing. By keeping the database state flexible enough to support the "n-1" version of your code, you decouple your deployment pipeline from strict database lock-step requirements. This allows your Argo Rollouts or standard deployments to shift traffic between versions without the database acting as a single point of failure during the transition.

Key Takeaway: Never execute destructive schema changes (dropping or renaming) in a single deployment; instead, use additive migrations that allow your database to support both old and new application versions simultaneously.