Article • Jul 2026 • 1 min read

Zero-Downtime Database Schema Migrations with PostgreSQL & Django

Techniques for adding NOT NULL columns, altering high-cardinality foreign keys, and safely renaming tables without acquiring destructive ACCESS EXCLUSIVE locks.

Dicky Joel Saputra
Dicky Joel Saputra
Backend Engineer
Zero-Downtime Database Schema Migrations with PostgreSQL & Django Technical Diagram

1. The ACCESS EXCLUSIVE Lock Threat

Executing python manage.py migrate on production tables with millions of active rows can bring down an entire API platform if an ALTER TABLE statement acquires an ACCESS EXCLUSIVE lock. This lock prevents even basic SELECT queries from executing.

Catastrophic Queue Behavior

Even a fast ALTER TABLE will queue behind long-running queries, subsequently blocking all incoming web traffic and exhausting the Gunicorn worker thread pool.

2. Safe 3-Step Procedure for NOT NULL Constraints

Instead of adding a NOT NULL constraint directly with a default value, PostgreSQL allows adding a CHECK constraint as NOT VALID instantaneously, backfilling data in small batches, and then validating the constraint asynchronously without holding destructive locks.

safe_not_null_migration.sql SQL
-- Step 1: Add column without default or constraint (Instant)
ALTER TABLE orders ADD COLUMN loyalty_points INT;

-- Step 2: Add CHECK constraint as NOT VALID (Zero lock time)
ALTER TABLE orders 
ADD CONSTRAINT check_loyalty_not_null 
CHECK (loyalty_points IS NOT NULL) NOT VALID;

-- Step 3: Backfill data in micro-batches
-- UPDATE orders SET loyalty_points = 0 WHERE id BETWEEN ...

-- Step 4: Validate constraint concurrently without blocking writes
ALTER TABLE orders VALIDATE CONSTRAINT check_loyalty_not_null;

Safe NOT NULL constraint validation in PostgreSQL with zero lock duration.

<production-migration-impact />

0.00 seconds
Downtime Duration
< 2 ms
Lock Wait Time
0 blocked
Connection Pool Spikes

<more_technical_deep_dives />

EndeavourOS is the Linux Distro I have always wanted
Golang Linux

EndeavourOS is the Linux Distro I have always wanted

After having to resolve a bunch of issues I was facing with Manjaro - …

Read Deep-Dive →
PostgreSQL Indexing Deep Dive: B-Tree, BRIN, and Partial Indexes for 10M+ Rows
Article

PostgreSQL Indexing Deep Dive: B-Tree, BRIN, and Partial Indexes for 10M+ Rows

When a high-volume financial transaction table crosses 10 million rows, naive sequential scans cripple …

Read Deep-Dive →
<collaborate />

Backend Running Slow? Let's Fix That.

Go concurrency, databases, deployment, docker — I handle it all, so your uptime stays solid and your system runs smooth.