Spring Boot: Blue-Green Deploy API dengan Rollback dan Postmortem adalah pendekatan yang cocok ketika tim ingin merilis perubahan API dengan risiko downtime serendah mungkin dan jalur rollback yang cepat. Intinya, kita menjalankan dua lingkungan identik, misalnya blue (aktif) dan green (kandidat rilis), lalu memindahkan trafik hanya setelah versi baru lolos verifikasi.

Untuk API Spring Boot, keberhasilan pola ini tidak hanya bergantung pada perpindahan trafik. Yang lebih penting adalah health check yang benar, readiness probe yang mencerminkan kesiapan nyata, smoke test pascadeploy, observability dasar, dan rollback yang sederhana. Tanpa itu, blue-green mudah berubah menjadi sekadar dua server yang sama-sama membingungkan saat insiden terjadi.

Mengapa Blue-Green Deploy Cocok untuk API Spring Boot

Pada pola blue-green, versi lama tetap melayani trafik normal sampai versi baru dinyatakan siap. Setelah itu, routing dipindahkan ke versi baru. Jika ditemukan masalah, trafik dapat dikembalikan ke versi lama tanpa perlu proses redeploy dari nol.

Keuntungan utama

  • Downtime minimal karena perpindahan trafik dilakukan saat kedua versi berjalan.
  • Rollback cepat karena versi sebelumnya masih aktif dan siap menerima trafik kembali.
  • Validasi lebih aman karena versi baru dapat diuji lebih dulu sebelum menerima trafik produksi penuh.
  • Risiko operasional lebih rendah dibanding deploy langsung menimpa instance aktif.

Trade-off yang perlu dipahami

  • Biaya infrastruktur sementara lebih tinggi karena dua lingkungan aktif bersamaan.
  • Butuh disiplin konfigurasi; blue dan green harus benar-benar setara kecuali versi aplikasinya.
  • Masalah stateful tidak hilang; sesi, cache, migrasi skema database, dan antrean tetap harus dirancang hati-hati.

Blue-green deploy aman untuk layer aplikasi, tetapi tidak otomatis aman untuk perubahan database yang tidak kompatibel mundur. Untuk API, prioritaskan perubahan skema yang backward compatible agar rollback tetap memungkinkan.

Arsitektur Rilis yang Sederhana dan Umum

Tanpa bergantung pada platform tertentu, arsitektur dasarnya bisa dipikirkan seperti ini:

  • Blue: versi yang sedang melayani trafik produksi.
  • Green: versi baru yang sudah dideploy tetapi belum menerima trafik publik penuh.
  • Load balancer atau reverse proxy: komponen yang menentukan ke mana trafik diarahkan.
  • Health endpoint: endpoint untuk mengecek status proses dan dependensi penting.
  • Smoke test: serangkaian verifikasi cepat setelah green hidup.
  • Observability: log, metrik, dan alert untuk mendeteksi regresi segera setelah cutover.

Alur rilis yang direkomendasikan

  1. Deploy versi baru ke lingkungan green.
  2. Jalankan health check dan readiness check pada green.
  3. Lakukan smoke test terhadap endpoint API penting.
  4. Verifikasi log, error rate, latensi, dan koneksi dependensi utama.
  5. Pindahkan trafik dari blue ke green.
  6. Pantau metrik beberapa menit pertama dengan ketat.
  7. Jika ada masalah, rollback dengan mengembalikan trafik ke blue.

Poin pentingnya: cutover dilakukan setelah verifikasi, bukan sebelum. Banyak kegagalan deploy terjadi karena health check hanya memastikan proses Java hidup, padahal aplikasi belum siap menerima request nyata.

Health Check dan Readiness Probe di Spring Boot

Untuk implementasi Spring Boot, Actuator adalah fondasi yang paling praktis. Endpoint health berguna untuk membedakan tiga kondisi yang sering tercampur:

  • Process alive: proses aplikasi berjalan.
  • Application ready: aplikasi siap menerima trafik.
  • Dependency healthy: dependensi penting seperti database atau message broker dapat diakses.

Konfigurasi dasar Actuator

Contoh berikut membuka endpoint health dan info. Detail properti dapat disesuaikan dengan kebutuhan keamanan dan operasional tim.

management.endpoints.web.exposure.include=health,info,metrics,prometheus
management.endpoint.health.show-details=always
management.health.probes.enabled=true

Jika lingkungan Anda tidak memakai endpoint metrics tertentu, cukup aktifkan yang relevan. Prinsipnya adalah membuka data yang dibutuhkan monitoring, tetapi tetap membatasi akses publik jika perlu.

Mengapa readiness lebih penting daripada sekadar health

Readiness seharusnya menjawab pertanyaan: apakah instance ini aman menerima trafik sekarang? Misalnya, aplikasi mungkin sudah hidup, tetapi:

  • koneksi database belum pulih,
  • cache penting belum terinisialisasi,
  • migrasi startup belum selesai,
  • konfigurasi eksternal belum termuat benar.

Jika load balancer hanya memeriksa bahwa port HTTP merespons, trafik bisa masuk terlalu cepat dan memicu error 5xx sesaat setelah rilis.

Menambahkan indikator health khusus

Untuk dependensi yang benar-benar kritis, Anda dapat menambahkan custom health indicator. Ini berguna jika kesiapan aplikasi tidak cukup diwakili oleh health bawaan.

import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.HealthIndicator;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;

@Component
public class DatabaseReadyHealthIndicator implements HealthIndicator {

    private final JdbcTemplate jdbcTemplate;

    public DatabaseReadyHealthIndicator(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

    @Override
    public Health health() {
        try {
            jdbcTemplate.queryForObject("select 1", Integer.class);
            return Health.up()
                    .withDetail("database", "reachable")
                    .build();
        } catch (Exception ex) {
            return Health.down(ex)
                    .withDetail("database", "unreachable")
                    .build();
        }
    }
}

Contoh di atas sederhana, tetapi berguna untuk menegaskan bahwa readiness harus memvalidasi hal yang benar-benar diperlukan aplikasi untuk melayani request.

Kesalahan umum pada health check

  • Terlalu dangkal: hanya memeriksa bahwa aplikasi merespons 200.
  • Terlalu berat: melakukan query mahal atau memeriksa terlalu banyak dependensi nonkritis.
  • Tidak membedakan liveness dan readiness: hasilnya, instance yang belum siap sudah menerima trafik.
  • Tidak sinkron dengan timeout infrastruktur: health check bisa dianggap gagal karena timeout terlalu pendek.

Smoke Test Setelah Deploy Green

Setelah green dinyatakan sehat, jangan langsung pindahkan semua trafik tanpa verifikasi perilaku dasar API. Smoke test harus singkat, cepat, dan fokus pada jalur paling penting.

Apa yang perlu diverifikasi

  • Endpoint utama merespons status HTTP yang benar.
  • Autentikasi atau otorisasi dasar tetap berfungsi.
  • Operasi baca penting berhasil.
  • Jika aman, satu operasi tulis sederhana berjalan normal.
  • Header, format JSON, dan validasi input tidak berubah secara tak sengaja.

Contoh smoke test sederhana dengan curl

curl -fsS http://green-host/actuator/health
curl -fsS http://green-host/api/v1/customers/123
curl -fsS -H "Authorization: Bearer TOKEN" http://green-host/api/v1/orders/active

Gunakan endpoint yang mewakili alur bisnis inti, bukan semua endpoint. Tujuannya adalah deteksi cepat terhadap regresi fatal, bukan pengganti test suite lengkap.

Kapan smoke test gagal walau health check lolos

  • Perubahan mapping URL atau serializer menyebabkan respons berbeda.
  • Konfigurasi security berubah dan menolak token yang sebelumnya valid.
  • Integrasi downstream hidup, tetapi data atau izin akses tidak sesuai.
  • Environment variable termuat, tetapi nilainya salah.

Inilah alasan health check dan smoke test harus diperlakukan sebagai dua lapisan berbeda.

Rollback Cepat yang Benar-Benar Bisa Dipakai

Rollback pada blue-green seharusnya sesederhana mengembalikan trafik ke blue. Jika rollback masih memerlukan build ulang, restart panjang, atau perubahan manual yang rawan salah, maka desain operasionalnya belum matang.

Prinsip rollback yang aman

  • Blue jangan dimatikan terlalu cepat setelah cutover ke green.
  • Perubahan database harus kompatibel mundur setidaknya selama masa observasi.
  • Konfigurasi release harus terdokumentasi agar tim tahu apa yang berubah selain artefak aplikasi.
  • Log dan metrik blue serta green harus bisa dibedakan agar diagnosis rollback jelas.

Langkah rollback operasional

  1. Deteksi gejala setelah cutover: error rate naik, latensi memburuk, atau endpoint inti gagal.
  2. Hentikan perluasan dampak: jangan lanjutkan scaling atau distribusi trafik tambahan ke green.
  3. Kembalikan routing ke blue.
  4. Verifikasi layanan pulih pada metrik utama.
  5. Bekukan rilis dan kumpulkan bukti untuk analisis akar masalah.

Poin penting: rollback bukan tanda kegagalan proses, melainkan bagian dari proses rilis yang sehat. Yang berbahaya justru menunda rollback karena berharap masalah “akan stabil sendiri”.

Observability Dasar: Log, Metrik, dan Alert

Setelah cutover, observability adalah alat utama untuk membedakan masalah nyata dari sinyal palsu. Untuk API Spring Boot, Anda tidak perlu langsung membangun sistem observability yang kompleks. Mulailah dari tiga lapisan: logging terstruktur, metrik inti, dan alert sederhana.

Logging terstruktur

Gunakan format log yang konsisten dan mudah diparsing. Minimal, sertakan:

  • timestamp,
  • level log,
  • nama service,
  • versi rilis atau identifier blue/green,
  • request id atau correlation id,
  • path, method, status code,
  • durasi request,
  • pesan error utama bila gagal.

Logging terstruktur mempermudah pencarian pola seperti “semua 500 hanya terjadi di green” atau “hanya endpoint tertentu yang terdampak”.

Contoh filter correlation id sederhana

import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.slf4j.MDC;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;
import java.util.UUID;

@Component
public class CorrelationIdFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(HttpServletRequest request,
                                    HttpServletResponse response,
                                    FilterChain filterChain) throws ServletException, IOException {
        String correlationId = request.getHeader("X-Correlation-Id");
        if (correlationId == null || correlationId.isBlank()) {
            correlationId = UUID.randomUUID().toString();
        }

        MDC.put("correlationId", correlationId);
        response.setHeader("X-Correlation-Id", correlationId);
        try {
            filterChain.doFilter(request, response);
        } finally {
            MDC.remove("correlationId");
        }
    }
}

Dengan pendekatan ini, pencarian log lintas komponen menjadi jauh lebih mudah saat insiden pascadeploy.

Metrik inti yang perlu dipantau

  • Request rate: apakah trafik benar-benar berpindah ke green.
  • Error rate: terutama 5xx dan lonjakan 4xx yang tidak biasa.
  • Latency: perhatikan median dan tail latency jika tersedia.
  • JVM basics: penggunaan heap, thread, dan garbage collection sebagai indikator kasar regresi runtime.
  • Dependency metrics: misalnya pool koneksi database dan timeout panggilan ke downstream.

Jika Anda sudah mengekspos metrik melalui Actuator, integrasikan dengan sistem monitoring yang tersedia di lingkungan tim. Tidak perlu membahas alat tertentu; yang penting adalah data ini bisa diamati selama dan setelah cutover.

Alert sederhana yang realistis

Pada tahap awal, cukup buat alert untuk kondisi berikut:

  • health endpoint gagal terus-menerus pada green,
  • error rate meningkat tajam setelah cutover,
  • latensi endpoint inti melonjak signifikan dibanding baseline normal,
  • smoke test otomatis gagal pascadeploy.

Hindari alert terlalu sensitif yang memicu kebisingan. Tujuan alert saat rilis adalah membantu keputusan cepat: lanjut, tahan, atau rollback.

Contoh Alur Rilis Blue-Green untuk API Spring Boot

Berikut alur yang bisa diterapkan tanpa mengikat ke platform tertentu:

  1. Build artefak dan jalankan test otomatis.
  2. Deploy ke green dengan konfigurasi yang setara dengan blue.
  3. Tunggu readiness hingga endpoint health menyatakan siap.
  4. Jalankan smoke test ke green secara langsung.
  5. Verifikasi observability: log bersih, error rate nol atau sesuai ekspektasi, latensi normal.
  6. Cutover trafik dari blue ke green.
  7. Pantau pascadeploy selama jendela observasi singkat.
  8. Retain blue sampai keyakinan cukup tinggi bahwa rilis stabil.

Jika ada otomatisasi CI/CD, urutan ini sebaiknya menjadi pipeline formal, bukan hanya pengetahuan lisan di kepala operator.

Skenario Insiden Ringan Setelah Rilis

Misalkan setelah cutover ke green, tim melihat gejala berikut dalam 3 menit pertama:

  • error 500 naik pada endpoint /api/v1/orders,
  • endpoint lain relatif normal,
  • health endpoint tetap UP,
  • log menunjukkan exception saat membaca konfigurasi timeout downstream.

Gejala dan isolasi dampak

Karena hanya satu jalur API yang terdampak, masalah kemungkinan bukan kegagalan total runtime. Ini mengarah ke regresi konfigurasi, perubahan kontrak downstream, atau bug logika spesifik endpoint. Langkah pertama adalah mengisolasi dampak:

  • cek apakah semua request gagal atau hanya subset tertentu,
  • cek apakah hanya green yang terdampak,
  • bandingkan environment variable blue vs green,
  • verifikasi perubahan konfigurasi release terakhir.

Jika dampaknya sudah menyentuh alur bisnis penting, rollback biasanya lebih tepat daripada debugging mendalam di produksi.

Rollback saat insiden

  1. Kembalikan trafik ke blue.
  2. Pastikan error rate kembali normal.
  3. Tandai rilis green sebagai dibekukan untuk investigasi.
  4. Simpan log, konfigurasi efektif, dan hasil smoke test sebagai bukti.

Rollback cepat mengurangi waktu paparan pengguna dan memberi ruang untuk analisis yang lebih tenang.

Analisis akar masalah singkat

Dari log ditemukan bahwa green menggunakan nilai timeout downstream yang kosong karena nama environment variable berubah saat refactor konfigurasi. Health endpoint tetap UP karena health check tidak memvalidasi konfigurasi tersebut, dan smoke test tidak menyentuh alur orders yang bergantung pada downstream tersebut.

Akar masalah singkatnya:

  • Pemicu teknis: perubahan nama properti konfigurasi tanpa verifikasi kompatibilitas environment.
  • Kesenjangan deteksi: readiness check terlalu umum dan smoke test kurang mencakup endpoint kritis.
  • Faktor proses: checklist rilis tidak mewajibkan diff konfigurasi blue vs green.

Postmortem Ringkas yang Berguna

Postmortem tidak perlu panjang, tetapi harus cukup jelas untuk mencegah pengulangan. Format sederhana berikut biasanya memadai:

1. Ringkasan insiden

Setelah blue-green cutover, endpoint orders pada green mengembalikan 500 akibat konfigurasi downstream tidak termuat benar. Rollback dilakukan dalam beberapa menit dan layanan pulih setelah trafik kembali ke blue.

2. Dampak

  • Gangguan pada satu alur API inti.
  • Durasi gangguan terbatas berkat rollback cepat.
  • Tidak ada kerusakan data permanen jika operasi tulis gagal sebelum diproses penuh.

3. Akar masalah

Perubahan konfigurasi tidak diverifikasi menyeluruh. Readiness check tidak memeriksa dependensi atau konfigurasi yang benar-benar dibutuhkan endpoint orders.

4. Deteksi

Masalah terdeteksi dari kenaikan error rate dan log exception, bukan dari readiness atau smoke test.

5. Tindakan perbaikan

  • Tambahkan validasi konfigurasi saat startup untuk properti kritis.
  • Perluas smoke test ke endpoint bisnis paling sensitif.
  • Tambahkan checklist perbandingan konfigurasi blue dan green.
  • Pertimbangkan feature flag untuk mengaktifkan jalur baru secara bertahap.

Postmortem yang baik fokus pada perbaikan sistem, bukan menyalahkan individu.

Tindakan Pencegahan Sebelum Rilis Berikutnya

Checklist rilis minimum

  • Artefak aplikasi sesuai commit yang disetujui.
  • Konfigurasi green sudah diverifikasi terhadap blue.
  • Endpoint Actuator untuk health dan metrics dapat diakses oleh sistem operasional yang tepat.
  • Readiness benar-benar memeriksa dependensi penting.
  • Smoke test mencakup endpoint bisnis kritis.
  • Dashboard log dan metrik siap dipantau saat cutover.
  • Jalur rollback sudah jelas dan pernah diuji.

Feature flag untuk mengurangi blast radius

Jika perubahan menyentuh perilaku besar, feature flag bisa lebih aman daripada langsung mengaktifkan seluruh fitur baru bersamaan dengan cutover. Blue-green memindahkan versi aplikasi, sedangkan feature flag mengontrol perilaku di dalam versi tersebut. Kombinasi keduanya berguna saat tim ingin:

  • merilis kode lebih dulu,
  • mengaktifkan fitur belakangan,
  • menonaktifkan fitur bermasalah tanpa rollback penuh.

Trade-off-nya adalah kompleksitas konfigurasi bertambah. Karena itu, feature flag perlu nama yang jelas, masa hidup terbatas, dan mekanisme pembersihan setelah tidak diperlukan.

Verifikasi konfigurasi sebagai bagian dari startup

Salah satu pencegahan paling efektif adalah gagal cepat saat properti penting hilang atau tidak valid. Daripada membiarkan aplikasi hidup lalu gagal saat menerima request tertentu, lebih baik startup ditolak lebih awal. Pendekatan ini membuat readiness lebih jujur dan mengurangi insiden “health hijau tetapi request merah”.

Kesalahan Umum pada Blue-Green Deploy API

  • Menganggap deploy selesai saat proses hidup, bukan saat API lolos verifikasi.
  • Melupakan kompatibilitas database sehingga rollback tidak aman.
  • Tidak membedakan log blue dan green, membuat diagnosis lambat.
  • Smoke test terlalu sedikit atau tidak relevan terhadap jalur bisnis utama.
  • Mematikan blue terlalu cepat sebelum jendela observasi selesai.
  • Tidak mendokumentasikan perubahan konfigurasi yang ikut dirilis.

Penutup

Spring Boot: Blue-Green Deploy API dengan Rollback dan Postmortem bukan sekadar pola infrastruktur, melainkan disiplin rilis. Agar benar-benar aman, tim perlu memastikan bahwa green tidak hanya hidup, tetapi juga siap menerima trafik, lolos smoke test, dan dapat diamati dengan log serta metrik yang memadai.

Mulailah dari hal yang paling berdampak: Actuator untuk health endpoint, readiness yang jujur, smoke test endpoint kritis, logging terstruktur, metrik inti, alert sederhana, dan prosedur rollback yang singkat. Setelah itu, lengkapi dengan checklist rilis, verifikasi konfigurasi, dan feature flag untuk mengurangi risiko pada rilis berikutnya.