QUICK START:PatternsErrors & FixesSecurityBenchmarksDevOps RecipesCheatsheetsInterviewCompareTopicsHTMLCSSJavaScriptTypeScriptPythonSQLReactNext.jsNode.jsLinux & UbuntuKotlinSwiftC# / .NETJavaGoRustC++DSASystem DesignDevOpsCybersecurityAI / ML
AdvancedDatabase & Storage

PostgreSQL Zero-Downtime Schema Migrations

Executing DDL commands in Postgres acquires aggressive locks. This recipe shows how to alter tables and build indexes without blocking application reads and writes.

PostgreSQL

Prerequisites

  • PostgreSQL 12+
  • Active application workload

Configuration Files

001_safe_migration.sql./migrations/001_safe_migration.sql
SET statement_timeout = '2s';\nSET lock_timeout = '1s';\n\n-- Add column without default to avoid table rewrite\nALTER TABLE users ADD COLUMN new_status VARCHAR(50);\n\n-- Build index concurrently (cannot run in transaction block)\nCOMMIT;\nCREATE INDEX CONCURRENTLY idx_users_status ON users(new_status);
Explanation:Enforces lock timeouts to prevent queueing blockages and uses CONCURRENTLY to build indexes in the background.

Verification Steps

1

Verifies the index exists.

$psql -c "\\d users"
Expected OutputIndexes:\n "idx_users_status" btree (new_status)

Production Gotchas

  • CREATE INDEX CONCURRENTLY can fail and leave an INVALID index. You must manually DROP and recreate it if this happens.

Frequently Asked Questions

Why not add a default value to the new column?

In Postgres < 11, adding a default value rewrites the entire table, causing massive downtime.