Cloud service dihentikan secara rutin: deployment mengganti instance, autoscaler mengurangi kapasitas, host reboot, dan scheduler menjadwalkan ulang workload. Jika proses langsung keluar ketika menerima termination signal, request yang sedang berjalan dapat gagal meskipun service sebenarnya sehat.

Graceful shutdown adalah protokol lifecycle kecil: berhenti menerima pekerjaan baru, biarkan pekerjaan berguna yang sudah berjalan selesai dalam suatu deadline, lalu lepaskan resource dan keluar.

Pisahkan readiness dari kesehatan proses

Proses yang sedang shutdown mungkin masih hidup, tetapi seharusnya tidak lagi menerima traffic baru.

Artinya, readiness dan liveness menjawab pertanyaan berbeda:

  • readiness: apakah load balancer seharusnya mengirim pekerjaan baru ke sini?
  • liveness: apakah proses masih berfungsi cukup baik untuk tetap berjalan?

Saat shutdown, tandai instance sebagai unready terlebih dahulu. Biarkan tetap hidup cukup lama untuk menyelesaikan request yang sudah diterima.

Jika proses keluar sebelum routing traffic bereaksi, client dapat terus mengirim request ke endpoint yang menghilang di tengah pemrosesan.

Berhenti menerima pekerjaan baru terlebih dahulu

Urutan shutdown yang umum adalah:

termination signal
  -> readiness false
  -> hentikan accept baru
  -> tunggu pekerjaan aktif
  -> tutup dependency
  -> proses keluar

Untuk HTTP server, “hentikan accept baru” dapat berarti menutup listening socket sambil mempertahankan koneksi yang sudah terbentuk cukup lama untuk menyelesaikan request saat ini.

Untuk worker, ini dapat berarti menghentikan sementara konsumsi queue sebelum menyelesaikan job yang sudah di-reserve.

Mekanismenya berbeda, tetapi urutannya sama: kurangi pekerjaan masuk sebelum menunggu pekerjaan saat ini habis.

Tetapkan deadline untuk draining

Graceful shutdown harus memiliki batas waktu. Request dapat hang, dependency dapat berhenti merespons, atau client dapat mempertahankan koneksi terbuka tanpa batas.

Pilih shutdown budget yang sesuai dengan termination grace period platform:

platform grace period: 30 s
routing propagation:    5 s
request drain budget:  20 s
cleanup reserve:        5 s

Angkanya spesifik workload. Bagian pentingnya adalah menyisakan waktu untuk cleanup akhir sebelum platform mengirim hard kill.

Request seharusnya sudah memiliki deadline masing-masing. Shutdown bukan alasan untuk membiarkan pekerjaan yang sudah ditinggalkan berjalan selamanya.

Drain koneksi berumur panjang secara sengaja

WebSocket, streaming HTTP response, dan koneksi berumur panjang lain tidak secara alami selesai dalam jendela deployment yang singkat.

Service mungkin perlu:

  • berhenti menerima stream baru;
  • memberi tahu client agar reconnect;
  • menutup koneksi dengan alasan spesifik aplikasi;
  • membiarkan connection draining milik load balancer menangani flow yang sudah terbentuk;
  • menetapkan usia maksimum atau shutdown deadline.

Tanpa policy, satu koneksi berumur panjang dapat mencegah graceful termination tanpa batas.

Koordinasikan dengan load balancer

Shutdown aplikasi dan routing traffic eksternal adalah dua sistem terpisah.

Bahkan setelah readiness berubah, load balancer, service discovery, proxy, atau sidecar mungkin memerlukan waktu untuk melihat update tersebut. Sisakan sedikit waktu propagasi dalam lifecycle jika environment memerlukannya.

Jangan gunakan fixed sleep sebagai satu-satunya mekanisme keamanan jika platform menyediakan sinyal readiness atau deregistration yang lebih kuat. Sleep mudah salah ukur dan menambah delay bahkan ketika routing sudah konvergen.

Perlakukan background work sebagai bagian dari shutdown

HTTP request bukan satu-satunya operasi yang sedang berjalan. Service sering menjalankan:

  • queue consumer;
  • scheduled task;
  • batch flusher;
  • telemetry exporter;
  • cache refresh;
  • asynchronous write.

Setiap komponen harus menentukan apakah pekerjaan perlu diselesaikan, di-checkpoint, dibatalkan, atau diserahkan saat termination.

Background goroutine, thread, atau task yang terus memulai pekerjaan baru setelah server mulai draining dapat mencegah proses keluar dengan bersih.

Tutup resource setelah pekerjaan berguna berhenti

Database pool, message client, file, dan telemetry exporter umumnya harus tetap tersedia selama request yang sedang berjalan masih membutuhkannya.

Menutup database pool sebelum request draining selesai menciptakan kegagalan di dalam pekerjaan yang justru ingin dipertahankan service.

Urutan cleanup harus mengikuti dependency:

hentikan producer
selesaikan consumer
flush telemetry terakhir
tutup shared client
keluar

Buat handler sadar terhadap cancellation

Ketika shutdown deadline habis, pekerjaan yang tersisa memerlukan cancellation signal.

Handler yang mengabaikan cancellation dapat terus memakai CPU atau menunggu dependency sampai proses dipaksa berhenti. Propagasikan cancellation ke database call, downstream HTTP request, dan operasi lain yang mendukungnya.

Karena itu, sistem yang graceful membutuhkan jalur completion sekaligus cancellation.

Uji termination di bawah beban

Server yang shutdown dengan benar saat idle tetap dapat gagal selama deployment dengan traffic aktif.

Pengujian yang berguna adalah:

  1. jalankan request representatif secara berkelanjutan;
  2. picu termination signal normal;
  3. pastikan instance menjadi unready;
  4. verifikasi pekerjaan baru berpindah ke tempat lain;
  5. ukur berapa banyak request yang sudah diterima berhasil selesai;
  6. pastikan proses keluar sebelum hard deadline.

Ulangi dengan request lambat dan koneksi berumur panjang.

Amati lifecycle shutdown

Sinyal yang berguna meliputi:

  • timestamp mulai dan selesai shutdown;
  • jumlah request aktif ketika draining dimulai;
  • request yang selesai selama drain;
  • request yang dibatalkan pada deadline;
  • koneksi terbuka;
  • queue job yang masih aktif;
  • jumlah forced termination;
  • persentil durasi shutdown.

Deployment yang secara rutin mencapai batas hard termination tidak benar-benar graceful, meskipun sebagian besar request kebetulan bertahan.

Kesalahan umum

Langsung keluar saat SIGTERM

Termination signal seharusnya memulai lifecycle, bukan melewatinya.

Tetap ready saat draining

Jika request baru terus masuk, jumlah pekerjaan aktif mungkin tidak pernah mencapai nol.

Resource yang diperlukan request yang sedang berjalan harus tetap tersedia sampai request tersebut selesai atau dibatalkan.

Setiap drain memerlukan durasi maksimum dan jalur forced cancellation.

Hanya menguji dengan HTTP request singkat

Streaming connection, worker, dan dependency lambat sering menjadi yang pertama memperlihatkan bug shutdown.

Jadikan shutdown sebagai jalur operasi normal

Graceful termination seharusnya dijalankan pada setiap deployment biasa, bukan hanya saat insiden langka. Ini membuat bug lifecycle terlihat ketika sistem sehat dan memberi operator keyakinan bahwa scale down tidak menimbulkan error yang sebenarnya dapat dihindari.

Infrastruktur cloud pada akhirnya akan menghentikan proses. Service yang andal bekerja sama dengan kenyataan itu dengan menarik diri dari traffic, menyelesaikan pekerjaan berguna dalam deadline terbatas, dan melepaskan dependency dalam urutan yang disengaja.