Zero-Downtime Database Migrations
|
This concept applies to all deployments of `pandurart` that involve database schema changes.
Schema migrations are executed by the dedicated |
Rolling updates and canary deployments require that old and new application versions run in parallel against the same database. A breaking schema change β such as renaming or removing a column β would cause one of the two versions to fail.
The solution is the Parallel Change pattern ↑PARALLEL-CHANGE, also known as Expand and Contract or Zero-Downtime Database Migration ↑EVODB. It decomposes every potentially breaking schema change into a sequence of fully backward-compatible steps.
1. π The Three-Phase Pattern
1.1. Phase 1 β Expand
The schema is extended in a backward-compatible way. New columns, tables, or indexes are added alongside the existing structures. No existing column is removed or renamed. The old application version continues to work unchanged.
<changeSet id="2024-06-01-001-expand" author="migration">
<!-- add new column; nullable so the old app can still INSERT without it -->
<addColumn tableName="events">
<column name="location_url" type="VARCHAR(2048)"/>
</addColumn>
</changeSet>
1.2. Phase 2 β Migrate / Transition
A new version of the application is deployed. It writes to both the old and the new column simultaneously and reads from the new column. During the rollout window, old instances still write only to the old column, so both columns must be kept consistent.
If existing rows must be backfilled, a data-migration changeset can be executed once all old instances are drained:
<changeSet id="2024-06-01-002-backfill" author="migration">
<sql>
UPDATE events
SET location_url = website
WHERE location_url IS NULL
AND website IS NOT NULL;
</sql>
</changeSet>
1.3. Phase 3 β Contract
Once all application instances run the new version and the old column is no longer written to or read from, a follow-up deployment removes it.
<changeSet id="2024-07-01-001-contract" author="migration">
<dropColumn tableName="events" columnName="website"/>
</changeSet>
| The Contract changeset is intentionally released in a separate deployment from the Expand changeset β never in the same release. |
3. β Rules to Follow
β |
Always add new columns as nullable or with a default value in the Expand phase. |
β |
Keep the Expand and Contract changesets in separate releases (separate Git tags / deployments). |
β |
Execute |
β |
Ensure all old instances are terminated before running the Contract changeset. |
β |
Each Liquibase changeset must be idempotent β never modify an already-applied changeset. |
β |
Never rename a column directly β use Expand (add new) β Migrate β Contract (drop old). |
β |
Never change the data type of an existing column in a single step. |
β |
Never add a |
4. π·οΈ Naming Convention for Changesets
Changeset IDs follow the convention:
<ISO-date>-<sequence>-<phase>
Examples:
-
2024-06-01-001-expand -
2024-06-01-002-backfill -
2024-07-01-001-contract
This makes the migration history self-documenting and allows teams to identify which phase a changeset belongs to at a glance.
5. β οΈ Relationship to Canary and Rolling Deployments
During a canary deployment, both the old (v1) and the new (v2) application version process live traffic simultaneously. The database schema must be valid for both versions at the same time.
The Expand phase is the enabler: it guarantees that both v1 and v2 are compatible with the current schema throughout the entire canary window.
6. π Further Reading and References
-
↑PARALLEL-CHANGE β Martin Fowler: ParallelChange β the canonical description of the pattern.
-
↑EVODB β Martin Fowler & Pramod Sadalage: Evolutionary Database Design β the broader methodology behind schema evolution.
-
↑REFACTORING-DB β Scott Ambler & Pramod Sadalage: Refactoring Databases β the reference book with a complete catalogue of database refactoring patterns.
-
↑LIQUIBASE β Liquibase: official documentation for the migration tool used by
db-updater. -
↑LIQUIBASE-ZDDT β Liquibase: Zero-Downtime Deployments with Liquibase.
-
↑EXPAND-CONTRACT β Martin Fowler: Expand Contract β a concise summary of the two outer phases.