Prompt Claude Code untuk migrasi PostgreSQL: perubahan yang aman
Pelajari prompt Claude Code untuk migrasi PostgreSQL yang aman: pola expand–contract, backfill, dan rencana rollback, serta apa yang harus diverifikasi di staging sebelum rilis.

Apa yang membuat perubahan skema PostgreSQL berisiko
Perubahan skema PostgreSQL tampak sederhana sampai berhadapan dengan trafik nyata dan data nyata. Bagian yang berisiko biasanya bukan SQL itu sendiri. Yang berbahaya adalah ketika kode aplikasi, keadaan basis data, dan waktu deployment tidak lagi sinkron.
Sebagian besar kegagalan bersifat praktis dan menyakitkan: sebuah deploy rusak karena kode lama mengakses kolom baru, sebuah migrasi mengunci tabel panas dan timeout melonjak, atau perubahan “cepat” diam-diam menghapus atau menulis ulang data. Bahkan ketika tidak ada yang crash, Anda bisa mengirim bug halus seperti default yang salah, konstraint yang rusak, atau indeks yang tidak selesai dibangun.
Migrasi yang dihasilkan AI menambah lapisan risiko lain. Alat dapat menghasilkan SQL yang valid tetapi tidak aman untuk beban kerja Anda, volume data Anda, atau proses rilis Anda. Mereka juga bisa menebak nama tabel, melewatkan lock yang berjalan lama, atau meremehkan rollback karena down migration sulit. Jika Anda menggunakan Claude Code untuk migrasi, Anda membutuhkan pembatas dan konteks konkret.
Ketika posting ini mengatakan suatu perubahan “aman”, itu berarti tiga hal:
- Kompatibel mundur: versi aplikasi lama dan baru bisa berjalan selama rollout.
- Terukur: Anda bisa mengukur progres dan mendeteksi masalah dengan cepat.
- Dapat dibalik: Anda memiliki rencana rollback yang bisa dijalankan saat tekanan.
Tujuannya agar migrasi menjadi pekerjaan rutin: dapat diprediksi, dapat dites, dan membosankan.
Aturan keselamatan yang harus diikuti sebelum menulis prompt
Mulailah dengan beberapa aturan yang tidak boleh dilanggar. Mereka menjaga model tetap fokus dan mencegah Anda mengirim perubahan yang hanya bekerja di laptop Anda.
Pisahkan pekerjaan menjadi langkah kecil. Perubahan skema, backfill data, perubahan aplikasi, dan langkah pembersihan adalah risiko berbeda. Menggabungkannya membuatnya lebih sulit melihat apa yang rusak dan lebih sulit melakukan rollback.
Utamakan perubahan aditif sebelum yang destruktif. Menambahkan kolom, indeks, atau tabel biasanya berisiko rendah. Mengganti nama atau menghapus objek adalah tempat terjadinya outage. Lakukan bagian yang aman dulu, pindahkan aplikasi, lalu hapus yang lama hanya ketika Anda yakin tidak digunakan.
Buat aplikasi toleran terhadap kedua bentuk untuk sementara. Kode sebaiknya bisa membaca kolom lama atau baru selama rollout. Ini menghindari perlombaan di mana beberapa server menjalankan kode baru sementara basis data masih lama (atau sebaliknya).
Perlakukan migrasi seperti kode produksi, bukan skrip cepat. Bahkan jika Anda membangun dengan platform seperti Koder.ai (backend Go dengan PostgreSQL, plus klien React atau Flutter), basis data dibagi oleh semuanya. Kesalahan mahal.
Jika Anda ingin satu set aturan ringkas untuk diletakkan di atas setiap permintaan SQL, gunakan hal seperti:
- Satu perubahan per migrasi: expand, lalu backfill, lalu pindah kode, lalu pembersihan.
- Hindari lock panjang: gunakan pembuatan indeks CONCURRENTLY dan batch kecil untuk update.
- Wajibkan rencana rollback untuk setiap langkah, termasuk bagaimana menghentikan tengah-tengah backfill.
- Wajibkan query verifikasi dan metrik sukses (jumlah baris, tingkat null, waktu).
- Wajibkan runbook: bagaimana menjalankan, apa yang dipantau, dan siapa yang dipanggil.
Contoh praktis: daripada mengganti nama kolom yang menjadi dependensi aplikasi Anda, tambahkan kolom baru, backfill pelan-pelan, deploy kode yang membaca baru lalu lama, dan baru nanti hapus kolom lama.
Apa yang harus disertakan dalam prompt agar Claude Code tetap grounded
Claude bisa menulis SQL yang cukup baik dari permintaan yang samar, tapi migrasi aman membutuhkan konteks. Perlakukan prompt Anda seperti brief desain kecil: tunjukkan apa yang ada, jelaskan apa yang tidak boleh rusak, dan definisikan apa arti “aman” untuk rollout Anda.
Mulai dengan menempelkan hanya fakta basis data yang penting. Sertakan definisi tabel plus indeks dan konstraint relevan (primary key, unique constraint, foreign key, check, trigger). Jika tabel terkait dilibatkan, sertakan cuplikan itu juga. Cuplikan kecil dan akurat mencegah model menebak nama atau melewatkan konstraint penting.
Tambahkan skala dunia nyata. Jumlah baris, ukuran tabel, laju tulis, dan puncak trafik harus mengubah rencana. “200M rows dan 1k writes/sec” berbeda dari “20k rows dan sebagian besar read.” Sertakan juga versi Postgres Anda dan bagaimana migrasi dijalankan dalam sistem Anda (transaksi tunggal vs beberapa langkah).
Jelaskan bagaimana aplikasi menggunakan data: bacaan penting, penulisan, dan job latar. Contoh: “API membaca berdasarkan email”, “worker mengupdate status”, atau “laporan memindai berdasarkan created_at.” Ini menentukan apakah Anda perlu expand/contract, feature flags, dan seberapa aman sebuah backfill.
Terakhir, eksplisitkan konstraint dan deliverable. Struktur sederhana bekerja baik:
- Cuplikan skema saat ini dan tujuan
- Asumsi skala (baris, writes/sec, jendela maintenance jika ada)
- Dependensi aplikasi (query/endpoint/job)
- Kendala keras (tanpa downtime, hindari lock panjang, hindari rewrite tabel penuh)
- Deliverables: SQL plus rencana run dalam bahasa biasa, verifikasi, dan rollback
Meminta SQL sekaligus rencana run memaksa model memikirkan urutan, risiko, dan apa yang harus diperiksa sebelum Anda kirim.
Expand/contract dalam bahasa sederhana (dan kapan digunakan)
Pola migrasi expand/contract mengubah database PostgreSQL tanpa merusak aplikasi saat perubahan berlangsung. Alih-alih satu switch berisiko, Anda membuat database mendukung bentuk lama dan baru untuk jangka waktu tertentu.
Bayangkan: tambahkan hal baru dengan aman (expand), alihkan trafik dan data secara bertahap, lalu baru hapus bagian lama (contract). Ini sangat berguna untuk pekerjaan berbantuan AI karena memaksa Anda merencanakan tahap tengah yang kompleks.
Empat fase
Alur praktis terlihat seperti ini:
- Expand: tambahkan kolom atau tabel baru nullable, tambahkan indeks jika perlu, dan tambahkan konstraint dengan cara yang menghindari blocking (mis. tambahkan konstraint sebagai NOT VALID bila sesuai).
- Compatibility: update aplikasi agar menangani kedua field. Ini bisa berarti dual-write (tulis ke kedua tempat) atau read-fallback (baca baru, fallback ke lama).
- Backfill: salin data lama ke yang baru dalam batch kecil, dengan checkpoint dan cara untuk melanjutkan.
- Contract: setelah yakin semuanya menggunakan jalur baru, perketat aturan (set kolom NOT NULL, validasi konstraint), lalu drop kolom atau tabel lama.
Gunakan pola ini setiap kali pengguna mungkin masih menggunakan kode aplikasi lama saat database berubah. Itu termasuk deployment multi-instance, aplikasi mobile yang update lambat, atau rilis yang migrasinya bisa memakan menit atau jam.
Taktik yang membantu adalah merencanakan dua rilis. Rilis 1 melakukan expand plus compatibility sehingga tidak ada yang rusak jika backfill belum selesai. Rilis 2 melakukan contract hanya setelah Anda mengonfirmasi kode baru dan data baru sudah ada.
Template prompt aman untuk migrasi expand/contract
Salin template ini dan isi bagian di dalam kurung. Ini memaksa Claude Code menghasilkan SQL yang dapat Anda jalankan, cek untuk membuktikan berhasil, dan rencana rollback yang bisa Anda ikuti.
You are helping me plan a PostgreSQL expand-contract migration.
Context
- App: [what the feature does, who uses it]
- Database: PostgreSQL [version if known]
- Table sizes: [rough row counts], write rate: [low/medium/high]
- Zero/near-zero downtime required: [yes/no]
Goal
- Change: [describe the schema change]
- Current schema (relevant parts):
[paste CREATE TABLE or \d output]
- How the app will change (expand phase and contract phase):
- Expand: [new columns/indexes/triggers, dual-write, read preference]
- Contract: [when/how we stop writing old fields and remove them]
Hard safety requirements
- Prefer lock-safe operations. Avoid full table rewrites on large tables when possible.
- If any step can block writes, call it out explicitly and suggest alternatives.
- Use small, reversible steps. No “big bang” changes.
Deliverables
1) UP migration SQL (expand)
- Use clear comments.
- If you propose indexes, tell me if they should be created CONCURRENTLY.
- If you propose constraints, tell me whether to add them NOT VALID then VALIDATE.
2) Verification queries
- Queries to confirm the new schema exists.
- Queries to confirm data is being written to both old and new structures (if dual-write).
- Queries to estimate whether the change caused bloat/slow queries/locks.
3) Rollback plan (realistic)
- DOWN migration SQL (only if it is truly safe).
- If down is not safe, write a rollback runbook:
- how to stop the app change
- how to switch reads back
- what data might be lost or need re-backfill
4) Runbook notes
- Exact order of operations (including app deploy steps).
- What to monitor during the run (errors, latency, deadlocks, lock waits).
- “Stop/continue” checkpoints.
Output format
- Separate sections titled: UP.sql, VERIFY.sql, DOWN.sql (or ROLLBACK.md), RUNBOOK.md
Dua baris ekstra yang membantu dalam praktik:
- Minta agar setiap langkah yang memblokir penulisan diberi label
RISK: blocks writes, plus kapan menjalankannya (off-peak vs anytime). - Paksa kejujuran tentang lock: "If you're not sure whether a statement takes an ACCESS EXCLUSIVE lock, say so and offer a safer option."
Operasi skema umum dan cara memintanya agar SQL lebih aman
Perubahan skema kecil masih bisa menyakiti jika mengambil lock panjang, menulis ulang tabel besar, atau gagal di tengah. Saat menggunakan Claude Code untuk migrasi, minta SQL yang menghindari rewrite dan menjaga aplikasi bekerja sementara database mengejar.
Menambahkan kolom dan default (tanpa lock panjang)
Menambahkan kolom nullable biasanya aman. Menambahkan kolom dengan default non-null bisa berisiko pada versi Postgres lama karena bisa me-rewrite seluruh tabel.
Pendekatan yang lebih aman adalah perubahan dua langkah: tambahkan kolom sebagai NULL tanpa default, backfill dalam batch, lalu set default untuk baris baru dan tambahkan NOT NULL setelah data bersih.
Jika Anda harus menegakkan default segera, minta penjelasan tentang perilaku lock untuk versi Postgres Anda dan rencana fallback jika waktu eksekusi lebih lama dari perkiraan.
Indeks, FK, konstraint, penghapusan
Untuk indeks pada tabel besar, minta CREATE INDEX CONCURRENTLY agar baca dan tulis tetap berjalan. Juga minta catatan bahwa itu tidak bisa dijalankan di dalam blok transaksi, yang berarti tool migrasi Anda perlu langkah non-transaksional.
Untuk foreign key, jalan yang lebih aman biasanya menambahkan konstraint sebagai NOT VALID dulu, lalu memvalidasi kemudian. Ini membuat perubahan awal lebih cepat sambil tetap menegakkan FK untuk penulisan baru.
Saat memperketat konstraint (NOT NULL, UNIQUE, CHECK), minta "bersihkan dulu, terapkan nanti." Migrasi harus mendeteksi baris buruk, memperbaikinya, lalu baru mengaktifkan aturan yang lebih ketat.
Jika Anda ingin checklist singkat untuk ditempel di prompt, buat singkat:
- Sertakan catatan tentang lock dan perkiraan runtime.
- Gunakan CONCURRENTLY untuk indeks besar dan sebutkan batasan transaksi.
- Prefer NOT VALID lalu VALIDATE untuk foreign key baru.
- Pisahkan backfill dari penegakan NOT NULL/UNIQUE.
- Hanya hapus objek setelah satu siklus rilis penuh dan memastikan tidak ada yang membacanya.
Meminta backfill data yang lambat, stabil, dan dapat dipulihkan
Backfill adalah tempat kebanyakan rasa sakit migrasi muncul, bukan ALTER TABLE. Prompt paling aman memperlakukan backfill seperti job terkontrol: dapat diukur, dapat dilanjutkan, dan ramah produksi.
Mulai dengan cek penerimaan yang mudah dijalankan dan sulit diperdebatkan: jumlah baris yang diharapkan, target tingkat null, dan beberapa spot check (mis. bandingkan nilai lama vs baru untuk 20 ID acak).
Lalu minta rencana batching. Batch menjaga lock singkat dan mengurangi kejutan. Permintaan yang bagus menentukan:
- Bagaimana melakukan batch (rentang primary key atau jendela waktu seperti created_at)
- Ukuran batch target (mis. 5.000 sampai 50.000 baris)
- Apakah perlu jeda antar batch pada tabel panas
- Bahwa setiap batch adalah satu transaksi jelas (bukan satu transaksi besar)
Wajibkan idempotensi karena backfill bisa gagal di tengah. SQL harus aman dijalankan ulang tanpa menggandakan atau merusak data. Pola umum: "update hanya dimana kolom baru IS NULL" atau aturan deterministik di mana input yang sama selalu menghasilkan output yang sama.
Juga jelaskan bagaimana aplikasi tetap benar saat backfill berjalan. Jika penulisan baru terus masuk, Anda butuh jembatan: dual-write di kode aplikasi, trigger sementara, atau logika read-fallback (baca baru jika ada, kalau tidak baca lama). Sebutkan pendekatan mana yang bisa Anda deploy dengan aman.
Terakhir, bangun kemampuan pause dan resume ke dalam desain. Minta pelacakan progres dan checkpoint, seperti tabel kecil yang menyimpan ID terakhir yang diproses dan query yang melaporkan progres (baris diupdate, ID terakhir, waktu mulai).
Contoh: Anda menambahkan users.full_name yang diturunkan dari first_name dan last_name. Backfill aman hanya mengubah baris di mana full_name IS NULL, berjalan dalam rentang ID, menyimpan ID terakhir yang diupdate, dan menjaga signup baru tetap benar lewat dual-write sampai perpindahan selesai.
Cara meminta rencana rollback yang bekerja di dunia nyata
Rencana rollback bukan hanya "tulis down migration." Ini dua masalah: membatalkan perubahan skema dan menangani data apa pun yang berubah saat versi baru hidup. Rollback skema sering mungkin. Rollback data sering tidak mungkin kecuali Anda merencanakannya.
Jadilah eksplisit tentang apa arti rollback untuk perubahan Anda. Jika Anda menghapus kolom atau menulis ulang nilai di tempat, minta jawaban realistis seperti: "Rollback mengembalikan kompatibilitas aplikasi, tetapi data asli tidak bisa dipulihkan tanpa snapshot." Kejujuran semacam itu yang menjaga Anda aman.
Minta trigger rollback yang jelas sehingga tidak ada perselisihan saat insiden. Contoh:
- Tingkat error atau latency melewati ambang selama 10 menit
- Rencana query regresi kritis (mis. seq scan pada tabel panas)
- Job backfill tertinggal lebih dari N jam
- Cek data gagal (null di tempat yang tidak boleh, duplikat, baris hilang)
- Langkah migrasi memblokir penulisan lebih lama dari X detik
Wajibkan paket rollback lengkap, bukan hanya SQL: down migration SQL (hanya jika aman), langkah aplikasi untuk tetap kompatibel, dan cara menghentikan job latar.
Polanya biasanya cukup:
Produce a rollback plan for this migration.
Include: down migration SQL, app config/code switches needed for compatibility, and the exact order of steps.
State what can be rolled back (schema) vs what cannot (data) and what evidence we need before deciding.
Include rollback triggers with thresholds.
Sebelum mengirim, ambil "safety snapshot" ringan agar Anda dapat membandingkan sebelum dan sesudah:
- Jumlah baris untuk tabel yang terpengaruh (dan subset kunci)
- Sekelompok query sampel dengan hasil yang diharapkan
- Agregat sederhana (sum, min/max) untuk kolom yang disentuh
- Daftar singkat ID untuk spot-check sebelum dan sesudah
Juga jelaskan kapan tidak perlu rollback. Jika Anda hanya menambahkan kolom nullable dan aplikasi dual-writing, perbaikan maju (hotfix kode, jeda backfill, lalu lanjut) sering lebih aman daripada revert dan menimbulkan lebih banyak drift.
Kesalahan umum yang harus diwaspadai dengan migrasi berbantuan AI
AI bisa menulis SQL dengan cepat, tapi tidak melihat basis data produksi Anda. Sebagian besar kegagalan terjadi saat prompt samar dan model mengisi celah.
Perangkap umum adalah melewatkan skema saat ini. Jika Anda tidak menempelkan definisi tabel, indeks, dan konstraint, SQL mungkin menargetkan kolom yang tidak ada atau melewatkan aturan unik yang membuat backfill menjadi operasi lambat dan berat lock.
Kesalahan lain adalah mengirim expand, backfill, dan contract dalam satu deploy. Itu menghapus jalur keluar Anda. Jika backfill berjalan lama atau error di tengah, Anda terjebak dengan aplikasi yang mengharapkan keadaan akhir.
Masalah yang sering muncul:
- Backfill yang tidak idempoten dan tanpa pelacakan progres
- Menambahkan NOT NULL, UNIQUE, atau FK sebelum membersihkan dan memvalidasi data
- Transaksi lama tanpa statement timeout atau lock timeout
- Tidak ada query verifikasi, sehingga masalah tersembunyi sampai pengguna mengalaminya
Contoh konkret: "mengganti nama kolom dan mengupdate aplikasi." Jika rencana yang dihasilkan mengganti nama dan backfill dalam satu transaksi, backfill lambat dapat menahan lock dan merusak lalu lintas produksi. Prompt yang lebih aman memaksa batch kecil, timeout eksplisit, dan query verifikasi sebelum menghapus jalur lama.
Apa yang harus diverifikasi di staging sebelum mengirim
Staging adalah tempat Anda menemukan masalah yang tak pernah muncul di basis data dev kecil: lock panjang, null tak terduga, indeks yang hilang, dan jalur kode terlupakan.
Pertama, periksa bahwa skema sesuai rencana setelah migrasi: kolom, tipe, default, konstraint, dan indeks. Sekilas tidak cukup. Satu indeks yang hilang bisa mengubah backfill aman menjadi bencana.
Lalu jalankan migrasi terhadap dataset realistis. Idealnya itu salinan produksi terbaru dengan field sensitif dimasking. Jika tidak bisa, setidaknya cocokkan volume produksi dan hotspot (tabel besar, row lebar, tabel dengan banyak indeks). Catat waktu tiap langkah supaya tahu ekspektasi di produksi.
Checklist singkat untuk staging:
- Skema sesuai rencana (kolom, tipe, konstraint, indeks)
- Waktu tercatat pada volume data realistis
- Kompatibilitas diuji: aplikasi lama dengan skema baru dan aplikasi baru dengan skema lama (jika rencana menyatakan begitu)
- Query verifikasi dijalankan: tingkat null, jumlah baris, cek orphan untuk FK baru, pembacaan sampel
- Sinyal operasional dipantau selama run: lock, deadlock, timeout, query lambat
Akhirnya, uji alur pengguna nyata, bukan hanya SQL. Buat, update, dan baca record yang disentuh oleh perubahan. Jika expand/contract direncanakan, pastikan kedua skema bekerja sampai pembersihan akhir.
Contoh realistis: mengubah kolom tanpa merusak pengguna
Bayangkan Anda punya kolom users.name yang menyimpan nama lengkap seperti "Ada Lovelace." Anda ingin first_name dan last_name, tapi tidak boleh merusak signup, profil, atau layar admin saat perubahan berjalan.
Mulai dengan langkah expand yang aman meski tidak ada perubahan kode yang dideploy: tambahkan kolom nullable, pertahankan kolom lama, dan hindari lock panjang.
ALTER TABLE users ADD COLUMN first_name text;
ALTER TABLE users ADD COLUMN last_name text;
Lalu update perilaku aplikasi agar mendukung kedua skema. Di Rilis 1, aplikasi harus membaca dari kolom baru bila ada, fallback ke name bila null, dan menulis ke kedua tempat sehingga data baru tetap konsisten.
Selanjutnya backfill. Jalankan job batch yang mengupdate potongan kecil baris per run, mencatat progres, dan bisa dijeda dengan aman. Misalnya: update users dimana first_name null dalam urutan ID naik, 1.000 per batch, dan log berapa baris berubah.
Sebelum memperketat aturan, validasi di staging:
- Signup baru mengisi
first_namedanlast_namedan tetap mengisiname - Pengguna lama tampil benar meski hanya
nameyang ada - Backfill bisa dihentikan dan dilanjutkan tanpa menduplikasi kerja
- Tidak ada null tak terduga setelah backfill selesai
- Query dasar pada
userstidak terasa lebih lambat
Rilis 2 memindahkan baca hanya ke kolom baru. Hanya setelah itu Anda menambahkan konstraint (mis. SET NOT NULL) dan menghapus name, idealnya di deploy terpisah nanti.
Untuk rollback, buat sederhana. Aplikasi tetap membaca name selama transisi, dan backfill dapat dihentikan. Jika harus rollback Rilis 2, alihkan baca kembali ke name dan biarkan kolom baru tetap ada sampai stabil.
Langkah selanjutnya: ubah prompt jadi rutinitas migrasi yang dapat diulang
Perlakukan setiap perubahan seperti runbook kecil. Tujuannya bukan prompt sempurna. Tujuannya rutinitas yang memaksa detail benar: skema, konstraint, rencana run, dan rollback.
Standarkan apa yang harus disertakan setiap permintaan migrasi:
- Skema saat ini dan perubahan tepat (tabel, kolom, indeks)
- Konstraint dan fakta lalu lintas (ukuran tabel, laju tulis, downtime yang diizinkan)
- Urutan rilis (expand, deploy app, backfill, contract)
- Bagaimana mengamati progres (query/metrik, runtime yang diharapkan)
- Langkah rollback (apa yang dibalik dulu, data apa yang mungkin tertinggal)
Putuskan siapa yang memegang tiap langkah sebelum menjalankan SQL. Pembagian sederhana mencegah "semua mengira orang lain melakukannya": developer memegang prompt dan kode migrasi, ops memegang penjadwalan produksi dan monitoring, QA memverifikasi perilaku staging dan edge case, dan satu orang memutus go/no-go terakhir.
Jika Anda membangun aplikasi lewat chat, membantu untuk menguraikan urutan sebelum menghasilkan SQL. Untuk tim yang memakai Koder.ai, Planning Mode adalah tempat yang wajar untuk menulis urutan itu, dan snapshot plus rollback dapat mengurangi dampak bila ada yang tak terduga saat rollout.
Setelah dikirim, jadwalkan pembersihan contract segera selagi konteks masih segar, supaya kolom lama dan kode kompatibilitas sementara tidak menggantung berbulan-bulan.
Pertanyaan umum
Mengapa perubahan skema PostgreSQL bisa merusak produksi meski SQL terlihat sederhana?
Perubahan skema berisiko ketika kode aplikasi, keadaan basis data, dan jadwal deployment tidak lagi sinkron.
Mode kegagalan umum:
- Kode aplikasi lama mengakses kolom/konstraint baru dan crash
- Migrasi mengambil kunci kuat pada tabel sibuk sehingga permintaan timeout
- Perubahan “kecil” menimpa atau menghapus data tanpa disadari
- Pekerjaan pada indeks/konstraint berjalan lebih lama dari perkiraan dan menyebabkan query melambat
Apa cara bawaan paling aman untuk mengubah skema tanpa downtime?
Gunakan pendekatan expand/contract:
- Expand: tambahkan kolom/tabel/indeks nullable dengan cara kompatibel
- Compatibility: deploy kode aplikasi yang bisa baca/tulis kedua bentuk
- Backfill: salin data dalam batch kecil dengan checkpoint
- Contract: perketat konstraint dan hapus field lama hanya setelah satu siklus rilis penuh
Ini menjaga agar versi aplikasi lama dan baru tetap bekerja selama rollout.
Risiko tambahan apa yang diperkenalkan oleh migrasi yang dihasilkan AI?
Model dapat menghasilkan SQL yang valid tetapi tidak aman untuk beban kerja Anda.
Risiko khusus AI:
- Menebak nama tabel/kolom atau melewatkan konstraint penting
- Mengusulkan migrasi ‘big bang’ yang menghapus opsi rollback
- Mengabaikan perilaku lock, batasan transaksi, dan waktu pembuatan indeks yang lama
- Berusaha meremehkan rollback (terutama saat data diubah atau dihapus)
Anggap keluaran AI sebagai draf: minta rencana run, pemeriksaan, dan langkah rollback.
Apa yang harus saya tempelkan ke prompt agar Claude Code tidak menebak?
Cantumkan hanya fakta yang bergantung pada migrasi:
- Cuplikan
CREATE TABLErelevan (plus indeks, FK, UNIQUE/CHECK, trigger) - Versi Postgres dan bagaimana migrasi dijalankan (transaksi tunggal vs multi-langkah)
- Skala: jumlah baris, ukuran tabel, laju penulisan, puncak lalu lintas
- Bagaimana aplikasi memakai data (bacaan/tulisan/pekerjaan penting)
- Kendala keras (tanpa downtime, hindari rewrite penuh, batas lock)
- Deliverable: UP SQL + query verifikasi + rencana rollback + runbook
Ini mencegah tebakan dan memaksa urutan yang benar.
Haruskah saya menggabungkan perubahan skema dan backfill dalam satu migrasi?
Aturan default: pisahkan.
Pembagian praktis:
- Migrasi 1: expand skema (kolom/tabel baru, mungkin konstraint NOT VALID)
- Deploy aplikasi: kode kompatibilitas (read-fallback atau dual-write)
- Job backfill: update bertahap dengan pelacakan progres
- Migrasi 2: contract (validasi konstraint, set NOT NULL, drop kolom lama)
Menggabungkan semuanya membuat kegagalan lebih sulit didiagnosis dan di-rollback.
Bagaimana cara menambahkan kolom baru dengan default tanpa menyebabkan lock lama?
Preferensi pola:
ADD COLUMN ... NULLtanpa default (cepat)- Backfill dalam batch
- Set default untuk baris baru
- Tambahkan
NOT NULLhanya setelah verifikasi
Menambahkan default non-null langsung bisa berisiko pada beberapa versi karena mungkin me-rewrite seluruh tabel. Jika perlu default segera, minta catatan tentang perilaku lock dan fallback yang lebih aman.
Kapan saya harus menggunakan CREATE INDEX CONCURRENTLY, dan apa risikonya?
Minta:
CREATE INDEX CONCURRENTLYuntuk tabel besar/sibuk- Catatan bahwa itu tidak bisa dijalankan dalam blok transaksi (tooling Anda harus mendukungnya)
- Perkiraan waktu dan apa yang dipantau (lock waits, latency query)
Untuk verifikasi, sertakan cek cepat bahwa indeks ada dan dipakai (mis. bandingkan EXPLAIN sebelum/sesudah di staging).
Apa cara paling aman menambahkan foreign key di tabel besar?
Gunakan NOT VALID dulu, lalu validasi kemudian:
- Tambah FK sebagai
NOT VALIDagar langkah awal kurang mengganggu - Jalankan
VALIDATE CONSTRAINTdi langkah terpisah saat Anda bisa memantau
Ini tetap menegakkan FK untuk penulisan baru sambil memberi kontrol kapan validasi mahal dilakukan.
Bagaimana cara meminta backfill yang tidak merusak produksi dan bisa dilanjutkan?
Backfill yang baik itu bertahap, idempoten, dan bisa dilanjutkan.
Persyaratan praktis:
- Batch berdasarkan rentang primary key atau jendela waktu
- Update hanya baris yang masih perlu (mis.
WHERE new_col IS NULL) - Simpan batch dalam transaksi singkat; jika perlu beri jeda antar batch
- Lacak progres (ID terakhir yang diproses, baris yang diubah, waktu mulai)
- Pastikan aplikasi tetap benar selama backfill (dual-write, trigger sementara, atau read-fallback)
Ini membuat backfill tahan terhadap lalu lintas nyata.
Seperti apa rencana rollback realistis untuk perubahan skema?
Tujuan rollback default: pulihkan kompatibilitas aplikasi dengan cepat, meskipun data tidak sepenuhnya kembali.
Rencana rollback yang dapat dipakai harus mencakup:
- Apakah SQL DOWN benar-benar aman; jika tidak, berikan runbook sebagai gantinya
- Urutan tepat: hentikan/jeda job backfill, deploy perubahan kode aplikasi, lalu langkah skema
- Trigger rollback yang jelas (error rate, latency, lock waits, cek data gagal)
- Pernyataan apa yang bisa di-rollback (skema) vs apa yang tidak (data)
Seringkali rollback paling aman adalah mengalihkan baca kembali ke field lama sambil meninggalkan kolom baru.