Rilis migrasi Supabase tanpa downtime tidak bergantung pada satu perintah deploy atau rollback. Pendekatan yang aman adalah membuat perubahan skema yang tetap dapat dipakai oleh aplikasi versi lama dan baru, merilis aplikasi secara bertahap melalui canary, lalu memantau autentikasi, RLS, API, dan query penting sebelum perubahan diperluas.

Prinsip utamanya adalah: aplikasi harus dapat di-rollback lebih cepat daripada skema database. PostgreSQL mendukung transaksi untuk banyak operasi DDL, tetapi rollback schema setelah data baru ditulis atau struktur lama dihapus dapat menyebabkan kehilangan data, konflik kontrak API, atau pemblokiran query. Karena itu, gunakan pola expand-contract, feature flag, dan migrasi perbaikan maju (forward fix).

Urutan rilis yang aman dengan pola expand-contract

Pola expand-contract memisahkan perubahan yang berpotensi merusak menjadi beberapa rilis kecil. Versi lama dan versi baru aplikasi dapat hidup bersamaan selama masa canary atau rolling deployment.

Contoh: mengganti kolom status

Misalnya aplikasi lama memakai orders.status, tetapi aplikasi baru memerlukan orders.fulfillment_status dengan format yang berbeda. Jangan langsung mengganti nama atau menghapus kolom lama.

  1. Expand: tambahkan kolom baru yang nullable atau memiliki default yang aman.
  2. Backfill: isi data lama secara bertahap.
  3. Dual write: selama transisi, aplikasi menulis ke kolom lama dan baru, atau gunakan trigger sementara bila memang diperlukan.
  4. Dual read atau read fallback: aplikasi baru membaca kolom baru, tetapi dapat memakai nilai lama bila data belum dimigrasikan.
  5. Cutover: setelah semua pembaca dan penulis lama tidak lagi aktif, jadikan kolom baru sebagai sumber utama.
  6. Contract: hapus kompatibilitas, constraint sementara, dan kolom lama pada rilis terpisah.
-- 001_expand_order_fulfillment_status.sql
alter table public.orders
  add column fulfillment_status text;

-- Hindari update satu transaksi besar pada tabel besar.
-- Jalankan backfill bertahap berdasarkan rentang id atau waktu.
update public.orders
set fulfillment_status = status
where fulfillment_status is null
  and id >= :start_id
  and id < :end_id;

Backfill sebaiknya dilakukan dalam batch kecil, dengan jeda dan pemantauan latency. Satu UPDATE besar dapat menghasilkan WAL berlebihan, lock lebih lama, peningkatan I/O, dan tekanan pada replika atau koneksi aplikasi.

Catatan: penambahan constraint, indeks, perubahan tipe kolom, dan operasi pada tabel besar perlu ditinjau khusus. Uji durasi, lock, serta rencana eksekusi di environment yang representatif sebelum produksi.

Pemeriksaan migration Supabase sebelum produksi

Sebelum menerapkan migration ke project Supabase produksi, jadikan migration sebagai artefak yang ditinjau seperti kode aplikasi. Jalankan migration pada database lokal atau environment staging yang skema dan volumenya sedekat mungkin dengan produksi.

Checklist review SQL

  • Pastikan migration memiliki urutan jelas dan tersimpan di version control.
  • Identifikasi operasi destruktif: DROP, penggantian tipe, penghapusan kolom, perubahan primary key, dan perubahan constraint.
  • Periksa dampak lock. Operasi yang menyentuh banyak baris atau menulis ulang tabel perlu dipisah.
  • Pastikan kolom baru kompatibel dengan aplikasi lama: nullable terlebih dahulu, default yang aman, atau kode aplikasi yang siap menangani NULL.
  • Gunakan indeks untuk pola query baru, tetapi validasi dampak pembuatannya pada tabel besar.
  • Periksa fungsi, trigger, view, dan RPC PostgreSQL yang bergantung pada tabel atau kolom yang berubah.
  • Pastikan perubahan pada schema yang diakses API tidak mengubah bentuk respons tanpa strategi kompatibilitas.

Validasi kontrak API dan RLS

Supabase mengekspos akses data melalui klien dan API sesuai konfigurasi schema, privilege, dan Row Level Security (RLS). Perubahan kolom atau policy dapat membuat aplikasi gagal walaupun migration SQL sukses.

  • Uji request sebagai pengguna anonim, pengguna terautentikasi, dan peran layanan yang memang digunakan server.
  • Verifikasi operasi SELECT, INSERT, UPDATE, dan DELETE untuk tabel terdampak.
  • Uji pengguna lintas organisasi/tenant untuk memastikan policy tidak membocorkan baris milik tenant lain.
  • Pastikan policy WITH CHECK masih mengizinkan payload baru saat insert atau update.
  • Uji alur login, refresh token, logout, dan endpoint yang membutuhkan klaim pengguna.
-- Contoh policy: pengguna hanya dapat membaca order miliknya.
alter table public.orders enable row level security;

create policy "read own orders"
on public.orders
for select
to authenticated
using (user_id = auth.uid());

Contoh tersebut hanya aman bila user_id benar-benar merepresentasikan pemilik data. Untuk model organisasi, policy biasanya juga perlu memverifikasi keanggotaan tenant, bukan hanya mencocokkan satu kolom.

Canary release aplikasi sebelum perluasan trafik

Migration yang kompatibel belum cukup bila kode aplikasi baru memperkenalkan query mahal, bug serialisasi, atau asumsi RLS yang keliru. Canary release membatasi dampak dengan mengarahkan sebagian kecil trafik ke versi aplikasi baru terlebih dahulu.

Urutan deploy yang direkomendasikan

  1. Terapkan migration fase expand yang tidak merusak aplikasi lama.
  2. Deploy aplikasi baru dengan feature flag dalam keadaan nonaktif atau hanya aktif untuk pengguna internal.
  3. Arahkan sebagian kecil trafik ke versi baru melalui mekanisme canary di platform deployment, gateway, atau load balancer.
  4. Bandingkan error rate, latency, hasil query, dan metrik bisnis versi canary dengan baseline.
  5. Naikkan porsi trafik secara bertahap jika indikator sehat.
  6. Aktifkan feature flag lebih luas setelah perilaku data tervalidasi.
  7. Jalankan fase contract hanya setelah versi lama benar-benar tidak melayani trafik dan masa observasi selesai.

Jika infrastruktur tidak mendukung pembagian trafik, canary tetap bisa dilakukan melalui allowlist pengguna internal, tenant uji, atau flag berbasis user ID. Pendekatan ini tidak merepresentasikan seluruh beban produksi, tetapi tetap efektif untuk memeriksa autentikasi, policy, dan alur bisnis utama.

Feature flag untuk memisahkan deploy dan aktivasi

Feature flag memungkinkan kode baru dirilis tanpa langsung mengubah perilaku semua pengguna. Flag harus memiliki pemilik, batas waktu penghapusan, dan fallback yang jelas. Jangan biarkan flag transisi permanen karena kompleksitas jalur kode akan meningkat.

function getFulfillmentStatus(order) {
  if (featureFlags.useNewFulfillmentStatus) {
    return order.fulfillment_status ?? order.status;
  }

  return order.status;
}

Dalam masa transisi, catat berapa banyak pembacaan yang masih memakai fallback. Nilai tersebut membantu menentukan apakah backfill belum lengkap atau ada penulis lama yang masih aktif.

Rollback: dahulukan aplikasi, jangan terburu-buru membalik schema

Rollback aplikasi umumnya aman bila migration memakai expand-contract: arahkan trafik kembali ke image atau revisi aplikasi sebelumnya, lalu nonaktifkan feature flag. Database tetap menyediakan kolom dan struktur yang dibutuhkan versi lama.

Sebaliknya, rollback schema tidak selalu aman. Contohnya, setelah aplikasi baru menulis data ke kolom baru, menghapus kolom tersebut akan membuang data. Membalik perubahan tipe dapat gagal karena terdapat nilai yang tidak dapat dikonversi. Mengembalikan policy lama juga dapat membuka akses yang sebelumnya sudah dibatasi.

Strategi ketika rilis bermasalah

  • Bug aplikasi tanpa kerusakan data: rollback aplikasi atau nonaktifkan flag, kemudian investigasi.
  • Query baru lambat: matikan jalur query melalui flag, kurangi trafik canary, lalu tambahkan atau perbaiki indeks berdasarkan rencana query.
  • Data baru tidak konsisten: hentikan penulisan fitur, identifikasi rentang data terdampak, perbaiki dengan migration atau job yang idempoten.
  • Migration sudah terlanjur diterapkan: prioritaskan forward fix, yaitu migration baru yang mengoreksi skema atau data tanpa menghapus bukti dan data yang sudah masuk.

Siapkan rencana rollback sebelum deploy: revisi aplikasi yang akan dipulihkan, flag yang harus dimatikan, query verifikasi, penanggung jawab keputusan, dan kriteria kapan canary harus dihentikan.

Dashboard, log, dan metrik yang harus dipantau

Gunakan dashboard Supabase dan observabilitas aplikasi untuk membandingkan periode sebelum, saat, dan setelah canary. Sertakan identifier rilis pada log aplikasi agar error dapat dikaitkan dengan versi tertentu.

Checklist observabilitas rilis

  • Aplikasi: request rate, error rate per endpoint, status 4xx/5xx, latency p50/p95/p99, timeout, dan exception baru.
  • Database: query latency, query terlama, jumlah koneksi aktif, error koneksi, lock atau query yang menunggu, serta konsumsi resource yang tersedia pada dashboard.
  • Auth: kegagalan login, refresh token gagal, respons 401/403, dan peningkatan error pada endpoint terproteksi.
  • RLS/API: perubahan jumlah respons kosong yang tidak wajar, error policy, 403, dan perbedaan hasil antara peran pengguna.
  • Data: jumlah write sukses, fallback read, nilai NULL yang tak terduga, duplikasi, serta kegagalan job backfill.
  • Bisnis: penyelesaian checkout, pembuatan order, atau alur inti lain yang relevan dengan perubahan.

Jangan hanya memantau rata-rata latency. Rata-rata dapat terlihat normal sementara sebagian pengguna mengalami query sangat lambat. Pisahkan metrik menurut versi rilis, endpoint, tenant bila relevan, dan jalur feature flag.

Triage saat error rate atau query latency meningkat

Tetapkan ambang tindakan sebelum rilis, misalnya kenaikan error atau latency yang bermakna dibanding baseline dan tidak pulih dalam jendela observasi yang disepakati. Ambang harus disesuaikan dengan karakteristik layanan, bukan angka generik.

  1. Batasi dampak: hentikan kenaikan trafik canary, nonaktifkan flag, atau rollback aplikasi.
  2. Konfirmasi korelasi: cocokkan waktu kenaikan metrik dengan waktu migration, aktivasi flag, dan deploy aplikasi.
  3. Kelompokkan error: pisahkan 401/403, validasi payload, timeout, error database, dan exception aplikasi berdasarkan endpoint serta versi rilis.
  4. Periksa query: cari query baru atau query yang frekuensinya meningkat. Gunakan rencana eksekusi pada environment aman bila perlu; jangan menjalankan eksperimen berat di produksi saat insiden aktif.
  5. Periksa lock dan koneksi: tentukan apakah ada transaksi panjang, migrasi/backfill yang masih berjalan, atau pool koneksi yang jenuh.
  6. Validasi data dan RLS: uji satu kasus pengguna terdampak dengan konteks peran yang benar untuk membedakan bug policy dari data yang belum dibackfill.
  7. Komunikasikan status: catat dampak, mitigasi aktif, dan waktu pembaruan berikutnya dalam kanal insiden.

Audit rilis dan postmortem ringan

Audit yang berguna tidak harus rumit. Simpan jejak siapa yang menyetujui migration, commit atau revisi aplikasi yang dirilis, waktu penerapan, feature flag yang aktif, hasil verifikasi, serta keputusan rollback atau forward fix. Hindari menyimpan token, payload sensitif, atau data pribadi di log audit.

Format postmortem tanpa menyalahkan individu

  • Ringkasan: apa yang terjadi dan dampak pengguna atau layanan.
  • Timeline: migration, deploy, aktivasi flag, deteksi, mitigasi, dan pemulihan.
  • Kondisi teknis: perubahan skema, jalur aplikasi, policy, atau query yang terlibat.
  • Mengapa kontrol tidak menangkapnya: gap pada test, alert, review, canary, atau dashboard.
  • Tindakan perbaikan: tindakan dengan pemilik dan tenggat, misalnya test RLS, indeks, alert query, atau perubahan runbook.
  • Pembelajaran: fakta sistem dan proses, bukan penilaian terhadap individu.

Pencegahan yang dapat dimasukkan ke CI/CD

Tujuan CI/CD adalah menghentikan perubahan berisiko sebelum mencapai produksi dan membuat prosedur rilis dapat diulang.

  • Jalankan migration pada database sementara atau staging dari awal, lalu jalankan test aplikasi terhadap skema hasil migration.
  • Tambahkan test integrasi untuk endpoint utama dengan konteks anonymous, authenticated, dan peran server yang diperlukan.
  • Tambahkan test negatif RLS: pengguna A tidak boleh membaca atau mengubah data pengguna atau tenant B.
  • Lint SQL dan wajibkan review untuk operasi destruktif atau migration yang menyentuh tabel besar.
  • Jalankan smoke test setelah deploy: login, request API utama, insert/read data, dan jalur feature flag.
  • Wajibkan approval manual untuk tahap produksi, terutama pada migration schema dan aktivasi feature flag global.
  • Simpan artefak deploy: checksum migration, revision aplikasi, hasil test, serta tautan dashboard dan log rilis.
  • Buat alert untuk lonjakan error, latency, kegagalan autentikasi, dan fallback read yang tetap tinggi setelah masa transisi.

Rilis yang aman di Supabase adalah rangkaian kontrol yang saling melengkapi: migration kompatibel, canary aplikasi, feature flag, verifikasi RLS dan API, observabilitas, serta kemampuan memulihkan perilaku aplikasi dengan cepat. Dengan urutan expand-contract, sebagian besar insiden dapat dibatasi tanpa perlu melakukan rollback schema yang berisiko.