Blue-Green Deployment Next.js adalah pendekatan rilis yang meminimalkan downtime dan mempercepat rollback dengan cara menyiapkan dua environment identik: satu aktif melayani trafik, satu lagi menjadi kandidat rilis berikutnya. Untuk aplikasi Next.js, strategi ini efektif jika dikombinasikan dengan health check yang benar, verifikasi dependency, guardrail seperti feature flag, dan rollback berbasis sinyal operasional seperti error rate serta latency.

Masalah yang sering muncul bukan pada proses build, tetapi pada cutover: aplikasi tampak sehat, namun koneksi database gagal, cache belum siap, migrasi tidak kompatibel, atau trafik dipindahkan terlalu cepat tanpa observability minimum. Artikel ini fokus pada implementasi praktis agar rilis Next.js lebih aman, rollback lebih cepat, dan insiden lebih mudah dicegah.

Arsitektur singkat Blue-Green Deployment untuk Next.js

Pada pola blue-green, Anda memiliki dua slot deployment:

  • Blue: environment yang saat ini menerima trafik produksi.
  • Green: environment baru yang berisi versi kandidat.

Proses dasarnya:

  1. Build dan deploy versi baru ke environment pasif.
  2. Jalankan health check, smoke test, dan verifikasi dependency.
  3. Jika lolos, alihkan trafik dari environment aktif ke environment baru.
  4. Pantau metrik penting beberapa menit setelah cutover.
  5. Jika error rate atau latency naik di luar batas, rollback dengan mengembalikan trafik ke environment lama.

Untuk aplikasi Next.js, arsitektur ini umumnya melibatkan beberapa komponen:

  • Reverse proxy atau load balancer untuk mengalihkan trafik.
  • Runtime aplikasi Next.js di dua environment identik.
  • Database yang dipakai bersama, sehingga migrasi harus dirancang backward-compatible.
  • Optional: cache, object storage, queue, dan layanan pihak ketiga.

Catatan penting: Blue-green deployment tidak otomatis aman jika database schema berubah secara tidak kompatibel. Di banyak kasus, risiko terbesar justru ada pada migrasi data, bukan pada switching trafik.

Kapan blue-green cocok dipilih?

Pendekatan ini cocok jika Anda membutuhkan:

  • Rollback cepat tanpa menunggu redeploy.
  • Rilis dengan downtime sangat rendah.
  • Validasi aplikasi baru di environment yang benar-benar mirip produksi.
  • Kontrol ketat saat merilis perubahan yang berisiko.

Trade-off-nya:

  • Biaya infrastruktur lebih tinggi karena ada dua environment aktif secara operasional.
  • Kompleksitas bertambah pada konfigurasi environment, secret, cache, dan migrasi database.
  • State eksternal seperti queue consumer dan job background perlu dikelola hati-hati agar tidak dijalankan ganda.

Prerelease checklist sebelum cutover

Sebelum trafik dipindahkan ke environment green, lakukan checklist yang singkat tetapi tegas. Tujuannya bukan membuat proses lambat, melainkan menangkap kegagalan yang paling mahal jika lolos ke produksi.

1. Validasi artefak build

  • Pastikan commit, tag, atau release ID yang dibangun sesuai perubahan yang direncanakan.
  • Pastikan build-time environment variable yang dibutuhkan Next.js tersedia.
  • Pastikan konfigurasi produksi tidak tertukar dengan staging.

2. Pastikan environment parity

Blue dan green harus sedekat mungkin. Jika green memakai konfigurasi berbeda, hasil verifikasi sebelum cutover menjadi kurang bermakna.

  • Versi runtime sama.
  • Secret dan kredensial sesuai scope produksi.
  • Network policy, DNS, dan akses dependency sama.
  • Konfigurasi cache, storage, dan queue konsisten.

3. Verifikasi health check aplikasi dan dependency

Health check jangan hanya mengembalikan HTTP 200 tanpa memeriksa hal penting. Minimal, bedakan antara:

  • Liveness check: proses aplikasi hidup dan dapat merespons.
  • Readiness check: aplikasi benar-benar siap menerima trafik.

Untuk readiness, periksa dependency kritis seperti database atau cache jika aplikasi membutuhkannya pada path utama.

4. Pastikan migrasi database aman

Jika release melibatkan perubahan schema, gunakan pendekatan expand and contract:

  1. Expand: tambahkan schema baru yang kompatibel dengan versi lama dan baru.
  2. Deploy aplikasi baru yang mulai memakai schema baru secara bertahap.
  3. Contract: hapus kolom atau perilaku lama setelah dipastikan tidak lagi dipakai.

Hindari langkah seperti mengganti nama kolom yang langsung dipakai aplikasi baru jika versi lama masih mungkin aktif saat rollback. Rollback aplikasi harus tetap bisa berjalan terhadap schema hasil migrasi.

5. Jalankan smoke test setelah deploy

Smoke test sebaiknya memverifikasi alur inti, bukan seluruh suite test. Fokus pada:

  • Homepage atau route utama.
  • Login atau session retrieval jika relevan.
  • API internal penting.
  • Akses data dasar dari database.
  • Asset statis atau route yang memanfaatkan rendering penting.

Implementasi health check pada aplikasi Next.js

Pola paling sederhana adalah menyediakan endpoint internal seperti /api/health atau route handler khusus yang mengembalikan status aplikasi dan dependency. Tujuannya bukan observability penuh, melainkan sinyal cepat apakah environment green layak menerima trafik.

Contoh endpoint health check

export async function GET() {
  const checks = {
    app: 'ok',
    database: 'unknown',
    cache: 'unknown'
  };

  let healthy = true;

  try {
    // Ganti dengan ping ringan ke database Anda
    await db.execute('SELECT 1');
    checks.database = 'ok';
  } catch {
    checks.database = 'fail';
    healthy = false;
  }

  try {
    // Ganti dengan ping ringan ke cache jika memang dependency kritis
    await cache.ping();
    checks.cache = 'ok';
  } catch {
    checks.cache = 'fail';
    // Tidak selalu harus unhealthy jika cache bersifat opsional
  }

  const status = healthy ? 200 : 503;

  return new Response(JSON.stringify({
    status: healthy ? 'ok' : 'degraded',
    checks,
    timestamp: new Date().toISOString()
  }), {
    status,
    headers: { 'content-type': 'application/json' }
  });
}

Prinsip pentingnya:

  • Readiness check boleh gagal jika database tidak tersedia.
  • Dependency opsional tidak harus membuat status menjadi 503.
  • Jangan memasukkan query berat ke health check.
  • Jangan membocorkan rahasia atau detail internal yang sensitif dalam response.

Kesalahan umum pada health check

  • Hanya memeriksa bahwa proses Node berjalan, padahal koneksi database mati.
  • Menjalankan query yang mahal sehingga health check sendiri menambah beban.
  • Menyamakan liveness dan readiness.
  • Menganggap semua dependency wajib, padahal beberapa bisa di-degrade sementara.

Verifikasi migrasi database yang aman untuk rollback

Blue-green deployment sering terlihat sederhana sampai menyentuh database bersama. Jika aplikasi baru menulis format data yang tidak dipahami aplikasi lama, rollback bisa gagal walaupun switching trafik sangat cepat.

Pola migrasi yang lebih aman

  • Tambah dulu, hapus belakangan: tambahkan tabel, indeks, atau kolom baru tanpa langsung menghapus yang lama.
  • Dual-read atau dual-write seperlunya: jika format berubah, sementara waktu dukung pembacaan dari format lama dan baru.
  • Backfill terpisah: untuk perubahan data besar, jangan gabungkan semuanya ke satu langkah deployment.
  • Kontrak kompatibel: aplikasi lama tetap bisa membaca dan menulis data yang sama selama masa transisi.

Checklist migrasi sebelum cutover

  • Apakah versi lama masih bisa berjalan setelah migrasi diterapkan?
  • Apakah migrasi bersifat idempoten atau setidaknya aman jika job retry?
  • Apakah ada lock panjang pada tabel yang akan menaikkan latency?
  • Apakah ada backfill besar yang sebaiknya dijalankan di luar jam sibuk?
  • Apakah rollback aplikasi tidak membutuhkan rollback schema secara darurat?

Jika jawaban untuk pertanyaan pertama adalah tidak, maka blue-green Anda belum benar-benar siap untuk rollback cepat.

Smoke test dan verifikasi pascadeploy

Setelah green selesai dideploy tetapi sebelum cutover penuh, jalankan smoke test terhadap environment green secara langsung. Jangan menunggu trafik pengguna menemukan bug dasar.

Contoh smoke test sederhana

#!/usr/bin/env bash
set -euo pipefail

BASE_URL="$1"

curl -fsS "$BASE_URL/" > /dev/null
curl -fsS "$BASE_URL/api/health" | grep '"status"'
curl -fsS "$BASE_URL/api/products?limit=1" > /dev/null

echo "Smoke test passed"

Tambahkan skenario sesuai aplikasi Anda, misalnya:

  • Memastikan halaman SSR dapat dirender.
  • Memastikan route API utama mengembalikan respons valid.
  • Memastikan aset statis dapat diambil dengan benar.
  • Memastikan autentikasi dasar atau pembacaan session bekerja.

Untuk perubahan berisiko, pertimbangkan synthetic check berkala setelah cutover agar sinyal error tidak hanya bergantung pada laporan pengguna.

Metrik minimum yang harus dipantau saat cutover

Rilis aman membutuhkan observability dasar. Anda tidak perlu stack monitoring yang rumit, tetapi minimal harus punya metrik yang cukup untuk memutuskan lanjut atau rollback.

Metrik aplikasi minimum

  • Error rate: persentase request gagal, terutama 5xx.
  • Latency: pantau minimal p95 atau metrik agregat yang konsisten.
  • Request volume: untuk memastikan trafik benar-benar mengalir ke environment baru.
  • Restart/crash: sinyal instabilitas proses.

Metrik dependency minimum

  • Latency query database.
  • Error koneksi database.
  • Timeout ke layanan eksternal.
  • Cache miss ekstrem atau koneksi cache gagal jika dependency itu kritis.

Log dan tracing minimum

  • Log aplikasi terstruktur dengan request ID atau correlation ID.
  • Log error yang memuat endpoint, status code, dan kategori error.
  • Tracing request penting jika tersedia, terutama untuk membedakan bottleneck aplikasi dan database.

Prinsip operasionalnya sederhana: tentukan ambang yang dapat diterima sebelum deployment dimulai. Jika sesudah cutover error rate naik tajam atau latency meningkat signifikan dibanding baseline normal, rollback lebih aman daripada menunggu terlalu lama.

Guardrail untuk mencegah insiden

Blue-green deployment membantu di level infrastruktur, tetapi banyak insiden terjadi karena perilaku aplikasi. Guardrail berfungsi sebagai rem tambahan.

1. Feature flag

Feature flag memungkinkan kode baru dirilis tanpa langsung mengaktifkan semua perilaku baru. Ini sangat berguna jika perubahan menyentuh alur bisnis atau dependency eksternal.

Gunakan feature flag untuk:

  • Mengaktifkan fitur per segmen pengguna.
  • Mematikan fitur bermasalah tanpa rollback penuh.
  • Memisahkan risiko deploy dari risiko release.

2. Read-only mode

Untuk operasi sensitif, siapkan mode baca-saja sementara. Ini berguna jika Anda mendeteksi masalah pada alur tulis namun masih ingin menjaga sebagian layanan tetap tersedia.

Contoh kasus:

  • Bug pada checkout atau form submit.
  • Masalah locking database saat migrasi atau backfill.
  • Ketidakstabilan layanan pihak ketiga untuk operasi write.

3. Rollout bertahap

Walaupun arsitekturnya blue-green, Anda tidak harus mengalihkan 100% trafik sekaligus. Jika load balancer mendukung pembagian trafik, lakukan bertahap:

  1. 0% ke green setelah deploy, hanya untuk smoke test internal.
  2. 5-10% untuk verifikasi awal.
  3. Naikkan bertahap sambil memantau error rate dan latency.
  4. 100% jika stabil.

Pendekatan ini menambah waktu rilis, tetapi sering lebih aman untuk perubahan besar.

4. Kill switch untuk integrasi eksternal

Jika aplikasi Next.js memanggil service pihak ketiga yang rentan timeout atau rate limit, sediakan flag untuk mematikan integrasi tertentu sementara waktu atau beralih ke fallback. Ini sering lebih cepat daripada rollback penuh jika akar masalah ada pada dependency eksternal.

Contoh alur deployment di CI/CD

Alur berikut bersifat generik agar tidak terikat vendor tertentu:

  1. Build: lint, test, dan build artefak Next.js.
  2. Deploy ke green: kirim artefak ke environment pasif.
  3. Run readiness checks: panggil endpoint health dan cek dependency kritis.
  4. Run smoke test: verifikasi route utama dan API penting.
  5. Apply safe migration: jika ada migrasi, jalankan langkah yang kompatibel dengan rollback.
  6. Cutover bertahap: alihkan trafik sebagian lalu penuh.
  7. Observe: pantau metrik minimum selama jendela verifikasi.
  8. Rollback jika perlu: kembalikan trafik ke blue dan nonaktifkan fitur baru jika relevan.

Contoh pipeline pseudo-YAML

steps:
  - name: install
    run: npm ci

  - name: test
    run: npm test

  - name: build
    run: npm run build

  - name: deploy-green
    run: ./scripts/deploy-green.sh

  - name: wait-until-ready
    run: ./scripts/check-health.sh https://green.example.internal/api/health

  - name: smoke-test-green
    run: ./scripts/smoke-test.sh https://green.example.internal

  - name: migrate-safe
    run: ./scripts/migrate-safe.sh

  - name: shift-traffic-10-percent
    run: ./scripts/shift-traffic.sh green 10

  - name: verify-metrics
    run: ./scripts/verify-metrics.sh

  - name: shift-traffic-100-percent
    run: ./scripts/shift-traffic.sh green 100

Urutan persis bisa berbeda. Sebagian tim menjalankan migrasi aman sebelum deploy aplikasi, sebagian setelah deploy green tetapi sebelum cutover. Kuncinya adalah menjaga kompatibilitas antara aplikasi lama, aplikasi baru, dan schema database.

Manajemen environment variable dan konfigurasi

Pada Next.js, sebagian konfigurasi dibaca saat build, sebagian saat runtime. Ini penting karena kesalahan env management sering membuat green lolos build tetapi gagal saat menerima trafik.

Praktik yang disarankan

  • Pisahkan variabel build-time dan runtime dengan jelas.
  • Jangan menaruh secret di variabel yang terekspos ke client.
  • Gunakan penamaan yang konsisten di blue dan green.
  • Validasi env wajib saat startup aplikasi.

Contoh validasi konfigurasi sederhana

const required = [
  'DATABASE_URL',
  'APP_BASE_URL'
];

for (const key of required) {
  if (!process.env[key]) {
    throw new Error(`Missing required env: ${key}`);
  }
}

Dengan validasi startup, kegagalan konfigurasi muncul lebih awal, bukan saat request pertama dari pengguna masuk.

Strategi rollback saat error rate atau latency naik

Rollback yang baik harus singkat, jelas, dan tidak bergantung pada analisis panjang di tengah insiden. Siapkan runbook sebelum deployment dimulai.

Kapan rollback dilakukan?

Contoh sinyal yang layak memicu rollback:

  • Error 5xx naik konsisten setelah cutover.
  • Latency naik signifikan dibanding baseline normal.
  • Endpoint kritis gagal pada synthetic check atau smoke test pascacutover.
  • Koneksi database atau dependency utama tidak stabil.

Langkah rollback operasional

  1. Bekukan rollout atau hentikan kenaikan persentase trafik ke green.
  2. Alihkan trafik kembali ke blue.
  3. Nonaktifkan feature flag baru jika ada.
  4. Aktifkan read-only mode jika masalah terkait operasi tulis dan rollback penuh belum cukup.
  5. Verifikasi metrik di blue kembali normal.
  6. Dokumentasikan waktu kejadian, gejala, dan tindakan.

Jika migrasi database sudah dijalankan, jangan terburu-buru melakukan rollback schema kecuali memang diperlukan dan telah diuji. Dalam banyak kasus, rollback aplikasi ke versi lama lebih aman jika schema dirancang kompatibel.

Debugging cepat setelah rollback

  • Bandingkan konfigurasi blue dan green.
  • Periksa log error yang paling sering muncul setelah cutover.
  • Bandingkan query atau endpoint yang latencynya melonjak.
  • Periksa apakah perubahan fitur baru dapat dimatikan tanpa redeploy.
  • Pastikan issue bukan berasal dari dependency eksternal yang kebetulan gagal saat deployment.

Contoh runbook rilis singkat

  1. Pastikan checklist prerelease selesai.
  2. Deploy ke green.
  3. Pastikan /api/health readiness bernilai sehat.
  4. Jalankan smoke test.
  5. Jalankan migrasi aman jika diperlukan.
  6. Alihkan 10% trafik ke green.
  7. Pantau error rate, latency, dan log selama beberapa menit.
  8. Jika stabil, naikkan ke 100%.
  9. Jika tidak stabil, rollback ke blue dan nonaktifkan fitur berisiko.
  10. Tutup rilis hanya setelah metrik stabil.

Postmortem ringan setelah insiden atau rollback

Rollback cepat menyelesaikan gejala, tetapi tanpa postmortem Anda berisiko mengulang masalah yang sama. Template berikut cukup ringan untuk dipakai tim kecil sampai menengah.

Template postmortem

Judul insiden:
Tanggal/Waktu:
Durasi:

Kronologi:
- 10:02 deploy ke green selesai
- 10:05 smoke test lolos
- 10:08 trafik dialihkan 20%
- 10:10 error 5xx naik pada endpoint /api/checkout
- 10:12 rollback ke blue
- 10:15 metrik kembali normal

Dampak:
- Endpoint terdampak:
- Persentase pengguna terdampak:
- Gejala utama:

Root cause:
- Penyebab teknis utama:
- Faktor kontribusi:

Aksi korektif:
- Perbaikan langsung yang dilakukan:
- Validasi sebelum rilis ulang:

Aksi pencegahan:
- Guardrail baru yang ditambahkan:
- Test/monitoring yang ditambahkan:
- Perubahan proses deployment:

Apa yang perlu dicari saat analisis akar masalah?

  • Apakah health check terlalu dangkal?
  • Apakah smoke test tidak mencakup endpoint kritis?
  • Apakah migrasi database tidak kompatibel dengan rollback?
  • Apakah tidak ada ambang rollback yang jelas?
  • Apakah feature flag atau read-only mode tidak tersedia?

Kesalahan yang paling sering terjadi

  • Menyamakan blue-green deployment dengan zero-risk deployment.
  • Menganggap HTTP 200 dari health endpoint berarti aplikasi siap produksi.
  • Merilis perubahan database yang tidak kompatibel dengan versi lama.
  • Melakukan cutover 100% tanpa observability minimum.
  • Tidak punya rollback plan yang diuji.
  • Tidak memisahkan deploy dan release, padahal feature flag bisa mengurangi risiko.

Penutup

Blue-Green Deployment Next.js efektif untuk rilis aman jika Anda memperlakukan deployment sebagai proses operasional yang terukur, bukan sekadar pemindahan artefak. Kunci utamanya adalah readiness check yang memeriksa dependency penting, migrasi database yang kompatibel dengan rollback, smoke test yang relevan, metrik minimum untuk keputusan cepat, dan guardrail seperti feature flag, read-only mode, serta rollout bertahap.

Jika tim Anda baru memulai, jangan langsung mengejar desain yang terlalu kompleks. Mulailah dari satu health endpoint yang benar, satu smoke test yang berguna, satu runbook rollback yang jelas, lalu tambah guardrail secara bertahap. Dalam praktik, kombinasi sederhana yang disiplin biasanya lebih efektif daripada pipeline canggih yang sulit dioperasikan saat insiden.