Menjadikan skema database seberkualitas kode aplikasi: migration-based schema dengan Flyway dan Alembic, review flow untuk perubahan database, strategi menghindari downtime saat deploy migration (expand-contract), serta pipeline CI/CD yang menjalankan migrasi secara otomatis dan aman

Bayangkan aplikasi dikelola dengan git — tapi perubahan tabel database dilakukan dengan psql manual di server produksi. Siapa yang membuat kolom itu? Kapan? Apa yang terjadi di rollback? Tidak ada yang tahu. Inilah masalah yang diselesaikan database version control: skema diperlakukan sebagai kode — versi, review, dan deploy otomatis.
Di episode 14 kita mengelola infrastruktur sebagai kode; sekarang giliran skema. Kombinasi keduanya (episode 14 + 17) menghasilkan database yang born from code, changed by PR, deployed by pipeline — fondasi praktik engineering modern yang sangat dicari.
Prinsipnya sederhana: setiap perubahan skema ditulis sebagai migration (file teks bernomor berurutan), dan tool memastikan setiap migration dijalankan tepat satu kali, dalam urutan. Skema database = urutan migration yang sudah dijalankan.
Perbandingan dua tool populer:
| Aspek | Flyway (Java/any) | Alembic (Python/SQLAlchemy) |
|---|---|---|
| Bahasa migration | SQL murni (atau Java) | Python + SQL |
| Tracking | Tabel flyway_schema_history | Tabel alembic_version |
| Kelebihan | Sederhana, SQL polos | Autogenerate dari model |
| Cocok | Tim backend apa pun | Tim Python |
Prinsip yang sama di kedua tool: file migration tidak boleh diubah setelah dijalankan di production — jika ada salah, tulis migration baru untuk memperbaikinya, bukan meng-edit yang lama.
Struktur project migration dengan Flyway:
db/migration/
├── V1__create_users.sql
├── V2__create_orders.sql
├── V3__add_status_to_orders.sql
└── V4__add_index_orders_status.sqlV1__create_users.sql:
CREATE TABLE users (
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
email TEXT NOT NULL UNIQUE,
full_name TEXT NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);Jalankan:
flyway -url=jdbc:postgresql://db:5432/appdb \
-user=admin -password=*** migratePerhatikan: konvensi penamaan V{nomor}__{deskripsi}.sql membuat urutan eksplisit. Flyway mencatat checksum — jika file di-edit setelah dijalankan, ia menolak (proteksi penting!). Di Python, padanannya: alembic revision -m "create users", lalu isi upgrade/downgrade, lalu alembic upgrade head.
Migration harus melalui review — seperti kode aplikasi. Flow yang sehat:
db-migrations.ALTER TABLE ... DROP COLUMN berbahaya, tidak ada perubahan yang memaksa downtime.Checklist review DBA yang praktis:
CREATE TABLE IF NOT EXISTS sebagai pengganti tracking.)UPDATE/DELETE massal dalam migration? Itu operasi data, bukan skema — dan berisiko lock. Pindahkan ke script terpisah.NOT NULL tanpa default? = downtime (lihat bagian expand-contract).Ini keterampilan paling berharga di episode ini. Masalah klasik: menambah kolom NOT NULL di tabel besar mengunci tabel (lock) selama migrasi — aplikasi macet. Solusinya expand-contract:
ALTER TABLE orders ADD COLUMN status TEXT;
CREATE INDEX idx_orders_status ON orders (status);UPDATE orders SET status = 'pending' WHERE status IS NULL
AND id BETWEEN 1 AND 100000;NOT NULL + tambahkan ke default privileges, lalu rilis aplikasi yang memakai kolom itu.Pola yang sama berlaku untuk rename kolom (buat kolom baru, dual-write, cutover) dan mengganti constraint. Inilah cara tim besar berdeploy setiap hari tanpa maintenance window.
Tip
Generalisasi yang berguna: deploy aplikasi dan migrasi tidak harus sinkron. Aplikasi versi lama harus tetap bekerja dengan skema baru (forward compatibility). Jika sebuah migration membuat aplikasi lama rusak, itu sinyal migration melanggar expand-contract — pisahkan menjadi langkah yang lebih kecil.
Pipeline migrasi yang sehat:
name: db-migrate
on:
push: { branches: [main] }
jobs:
migrate-staging:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Jalankan migrasi ke staging
run: flyway -url=$STAGING_DB_URL -user=$STAGING_DB_USER migrate
migrate-production:
runs-on: ubuntu-latest
environment: production
needs: migrate-staging
steps:
- name: Jalankan migrasi ke production
run: flyway -url=$PROD_DB_URL -user=$PROD_DB_USER migratePoin penting dalam pipeline:
down (Alembic) atau migration korektif (Flyway), dan selalu punya strategi (pola episode 11).UPDATE jutaan baris di migration mengunci tabel dan memperlama deploy. Pisahkan jadi backfill batch.Inti yang harus dibawa pulang:
Di episode 18 selanjutnya kita menyegel jaringan: network security & TLS — firewall dan private networking VPC, konfigurasi TLS/mTLS yang benar, serta VPN peering untuk menghubungkan lingkungan tanpa membuka port ke internet. Sampai jumpa di episode 18!