Canary deploy di Laravel adalah teknik rilis bertahap: versi baru hanya menerima sebagian kecil trafik lebih dulu, lalu dinaikkan jika metrik tetap sehat. Tujuannya bukan sekadar mengurangi risiko, tetapi memberi cara objektif untuk memutuskan apakah rilis aman dilanjutkan atau harus di-rollback.
Supaya pendekatan ini benar-benar berguna, Anda perlu tiga hal: indikator kesehatan aplikasi, batas keputusan berbasis SLO/SLI, dan prosedur rollback yang realistis. Artikel ini fokus pada implementasi praktis di Laravel tanpa bergantung pada vendor tertentu.
Mengapa canary deploy lebih aman daripada rilis sekaligus
Pada rilis langsung ke 100% trafik, bug baru akan muncul pada skala penuh. Jika ada masalah di query database, job queue, atau dependency eksternal, dampaknya langsung luas. Dengan canary deploy, Anda membatasi blast radius:
- Versi baru menerima sebagian kecil trafik, misalnya 1%, 5%, lalu 25%.
- Metrik diamati pada setiap tahap.
- Jika error rate, latency, atau kegagalan job meningkat, rollout dihentikan atau dibatalkan.
Canary deploy bukan pengganti test, staging, atau review code. Canary adalah lapisan kontrol tambahan untuk masalah yang baru terlihat pada trafik nyata: data produksi yang tidak terduga, beban puncak, integrasi eksternal, dan kondisi race.
SLI dan SLO untuk keputusan lanjut atau rollback
Kesalahan umum saat menjalankan canary deploy adalah memakai penilaian subjektif seperti “sepertinya aman”. Lebih baik gunakan SLI (service level indicator) yang bisa diukur, lalu tetapkan SLO (target layanan) sebagai ambang keputusan.
SLI minimum yang relevan untuk Laravel
- Error rate HTTP: persentase respons 5xx atau kegagalan endpoint penting.
- Latency: misalnya p95 atau p99 untuk endpoint utama.
- Queue/job failure: jumlah job gagal, retry yang melonjak, atau backlog queue.
- Health dependency: koneksi database, cache, queue backend, atau layanan internal yang wajib tersedia.
- Error aplikasi: exception tak tertangani, log level error/critical yang meningkat.
Contoh aturan keputusan yang praktis
Anda tidak harus punya sistem SRE yang kompleks untuk mulai. Cukup tetapkan aturan sederhana dan konsisten, misalnya:
- Naikkan trafik canary hanya jika error rate versi canary tidak lebih buruk secara signifikan dibanding stable.
- Batalkan rollout jika p95 latency endpoint utama naik tajam dan bertahan selama beberapa interval observasi.
- Batalkan rollout jika job failure meningkat setelah versi baru aktif.
- Jangan lanjutkan rollout hanya karena health check lulus; health check hanya syarat minimum, bukan bukti aplikasi sehat di beban nyata.
Catatan: Hindari angka target yang terlalu presisi jika Anda belum punya baseline historis. Mulai dari perbandingan canary vs stable dan gunakan tren yang jelas. Setelah beberapa rilis, baru perketat ambang berdasarkan data riil.
Arsitektur canary deploy Laravel yang sederhana
Secara umum, Anda menjalankan dua versi aplikasi secara bersamaan:
- Stable: versi yang saat ini melayani mayoritas trafik.
- Canary: versi baru yang menerima sebagian kecil trafik.
Pembagian trafik biasanya dilakukan di layer reverse proxy, ingress, atau load balancer. Artikel ini tidak membahas tool spesifik, tetapi prinsipnya sama: route sebagian request ke pool canary, ukur metriknya, lalu putuskan lanjut atau rollback.
Di sisi aplikasi Laravel, yang perlu disiapkan adalah:
- Endpoint health check yang ringan dan jelas tujuan penggunaannya.
- Logging terstruktur agar canary mudah dibedakan dari stable.
- Konfigurasi environment untuk menandai release, channel log, dan flag fitur.
- Migrasi database yang kompatibel dengan dua versi aplikasi yang berjalan bersamaan.
Implementasi health check di Laravel
Health check jangan disamakan dengan endpoint bisnis biasa. Tujuannya adalah memberi sinyal cepat apakah instance siap menerima trafik dan apakah dependency penting masih tersedia.
Pisahkan liveness dan readiness
- Liveness: proses aplikasi hidup dan bisa merespons.
- Readiness: instance siap melayani request karena dependency yang dibutuhkan tersedia.
Liveness sebaiknya sangat ringan. Readiness boleh mengecek database, cache, atau queue backend, tetapi tetap singkat agar tidak menambah beban berlebihan.
Contoh route health check
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Route;
Route::get('/health/live', function () {
return response()->json([
'status' => 'ok',
'app' => config('app.name'),
'release' => env('APP_RELEASE', 'unknown'),
]);
});
Route::get('/health/ready', function () {
$checks = [
'database' => false,
'cache' => false,
];
try {
DB::select('SELECT 1');
$checks['database'] = true;
} catch (\Throwable $e) {
}
try {
Cache::put('healthcheck', 'ok', 10);
$checks['cache'] = Cache::get('healthcheck') === 'ok';
} catch (\Throwable $e) {
}
$ok = !in_array(false, $checks, true);
return response()->json([
'status' => $ok ? 'ok' : 'degraded',
'release' => env('APP_RELEASE', 'unknown'),
'checks' => $checks,
], $ok ? 200 : 503);
});Hal yang perlu diperhatikan
- Jangan masukkan query berat, akses banyak tabel, atau call API eksternal lambat ke health check readiness.
- Jika aplikasi Anda sangat bergantung pada queue untuk alur kritis, lebih baik pantau queue lewat metrik terpisah daripada membuat endpoint readiness mahal.
- Pastikan response menyertakan identitas release agar observasi canary lebih mudah.
Konfigurasi env dan identitas release
Salah satu masalah saat insiden deploy adalah sulit membedakan log atau error dari versi mana. Karena itu, setiap release sebaiknya punya identitas yang jelas.
APP_NAME="my-laravel-app"
APP_ENV=production
APP_RELEASE=2026-06-11_01
CANARY_ENABLED=true
FEATURE_NEW_CHECKOUT=false
LOG_CHANNEL=stack
LOG_LEVEL=infoAPP_RELEASE berguna untuk:
- ditulis ke log,
- ditampilkan pada health check,
- membantu korelasi saat membandingkan stable vs canary.
FEATURE_NEW_CHECKOUT adalah contoh feature toggle. Ini penting karena deploy kode dan aktivasi fitur sebaiknya bisa dipisahkan. Jika ada masalah pada fitur baru, Anda bisa mematikannya tanpa harus selalu rollback seluruh release.
Observability minimum yang sebaiknya ada
Canary deploy tanpa observability hanya memindahkan risiko, bukan mengelolanya. Anda tidak perlu stack observability yang rumit, tetapi minimal harus bisa menjawab: versi baru error di mana, kapan, seberapa banyak, dan berdampak ke jalur mana?
1. Log terstruktur
Gunakan format log yang konsisten dan sertakan konteks penting seperti release, route, request id, user id jika aman, dan exception class.
return [
'default' => env('LOG_CHANNEL', 'stack'),
'channels' => [
'stack' => [
'driver' => 'stack',
'channels' => ['single'],
],
'single' => [
'driver' => 'single',
'path' => storage_path('logs/laravel.log'),
'level' => env('LOG_LEVEL', 'info'),
],
],
];Tambahkan konteks log dari middleware atau exception handler agar semua event penting menyertakan release.
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;
class RequestContext
{
public function handle($request, Closure $next)
{
$requestId = (string) Str::uuid();
Log::withContext([
'request_id' => $requestId,
'release' => env('APP_RELEASE', 'unknown'),
'path' => $request->path(),
'method' => $request->method(),
]);
$response = $next($request);
$response->headers->set('X-Request-Id', $requestId);
return $response;
}
}Dengan ini, saat ada lonjakan error di canary, Anda bisa cepat memfilter log berdasarkan release.
2. Error rate
Ukur jumlah respons 5xx, exception tak tertangani, dan endpoint yang sering gagal. Jika tidak punya APM penuh, setidaknya agregasikan dari access log dan application log.
3. Latency
Pantau latency untuk endpoint kritis, bukan rata-rata semua endpoint. Rata-rata sering menipu karena tertutup endpoint ringan. Fokuslah pada p95 untuk route penting seperti checkout, login, atau endpoint API yang paling sering dipakai.
4. Queue dan job failure
Banyak insiden Laravel muncul bukan di request sinkron, tetapi di worker queue setelah deploy. Pantau:
- jumlah job gagal,
- retry yang berulang,
- waktu tunggu queue yang meningkat,
- worker crash atau restart berulang.
Jika canary menyentuh alur async, verifikasi worker juga memakai release yang benar dan kompatibel dengan payload job yang sudah ada.
Migration yang aman untuk deploy bertahap
Ini bagian yang paling sering merusak canary deploy. Jika stable dan canary berjalan bersamaan, database harus kompatibel dengan keduanya. Hindari perubahan skema yang memaksa semua instance langsung pindah serentak.
Pola aman: expand and contract
Gunakan dua tahap:
- Expand: tambahkan kolom/tabel/index baru tanpa menghapus yang lama.
- Deploy aplikasi: versi baru mulai membaca/menulis format baru, idealnya tetap kompatibel dengan format lama.
- Contract: setelah semua instance stabil dan data sudah bermigrasi, baru hapus kolom atau perilaku lama.
Contoh migration aman
Misalnya Anda ingin mengganti full_name menjadi display_name. Jangan langsung rename dan ubah semua kode sekaligus.
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration {
public function up(): void
{
Schema::table('users', function (Blueprint $table) {
$table->string('display_name')->nullable()->after('full_name');
});
}
public function down(): void
{
Schema::table('users', function (Blueprint $table) {
$table->dropColumn('display_name');
});
}
};Pada tahap aplikasi, tulis ke dua kolom sementara waktu, dan baca dengan fallback:
$user->display_name = $input['display_name'] ?? $input['full_name'] ?? null;
$user->full_name = $input['full_name'] ?? $user->display_name;
$user->save();Setelah semua instance baru stabil dan backfill selesai, barulah Anda hapus penggunaan kolom lama. Pendekatan ini penting karena saat canary aktif, request bisa masuk ke versi lama maupun baru dalam waktu yang sama.
Kesalahan umum pada migration
- Drop kolom lama sebelum semua instance berhenti membacanya.
- Mengubah tipe data yang dipakai kode lama tanpa kompatibilitas.
- Menjalankan migration berat di jam sibuk tanpa rencana observasi.
- Menganggap rollback aplikasi otomatis berarti rollback database juga aman. Sering kali tidak.
Prinsip penting: rollback aplikasi harus tetap mungkin dilakukan meskipun migration sudah terlanjur jalan. Karena itu, desain migration untuk kompatibilitas mundur, bukan hanya sukses saat forward deploy.
Alur canary deploy yang praktis
1. Pra-deploy
- Pastikan release punya identitas unik.
- Pastikan alarm dasar aktif: error rate, latency endpoint kritis, queue failure.
- Verifikasi migration bersifat backward-compatible.
- Siapkan feature toggle untuk fitur berisiko tinggi.
- Siapkan runbook: siapa yang memutuskan rollback, apa langkahnya, dan metrik apa yang dilihat.
2. Deploy ke canary
- Rilis versi baru ke sebagian kecil instance.
- Pastikan endpoint
/health/livedan/health/readysehat. - Arahkan sebagian kecil trafik ke canary.
3. Observasi
Amati selama interval yang cukup untuk menangkap request sinkron dan efek async:
- error rate route penting,
- p95 latency,
- jumlah exception per release,
- queue backlog dan failed jobs,
- anomali log.
4. Keputusan
- Lanjutkan rollout jika canary setara atau lebih baik dari stable.
- Tahan rollout jika ada sinyal meragukan tetapi belum jelas.
- Rollback jika ada degradasi nyata atau alarm melewati ambang.
5. Full rollout dan verifikasi pascadeploy
Setelah trafik dinaikkan ke 100%, jangan langsung menganggap deploy selesai. Banyak masalah baru muncul saat volume penuh atau setelah job async berjalan lebih lama. Lakukan verifikasi pascadeploy minimal 15-30 menit atau sesuai karakter sistem Anda.
Checklist rollback tanpa janji zero-downtime palsu
Banyak tim mengklaim zero downtime, padahal rollback mereka gagal karena cache config belum sinkron, worker masih menjalankan kode lama, atau migration tidak kompatibel. Lebih jujur dan aman jika Anda menyiapkan rollback yang realistis.
Checklist rollback aplikasi
- Hentikan kenaikan trafik ke canary.
- Arahkan trafik canary kembali ke stable.
- Nonaktifkan feature toggle yang terkait jika itu cukup mengurangi dampak.
- Pastikan worker queue yang memakai release bermasalah dihentikan atau diganti secara terkendali.
- Verifikasi health check dan metrik stable kembali normal.
- Komunikasikan status insiden dan waktu rollback secara singkat ke tim terkait.
Jika migration sudah berjalan
Jangan terburu-buru menjalankan migrate:rollback di produksi hanya karena aplikasi di-rollback. Pertanyaan utama adalah: apakah stable masih kompatibel dengan skema saat ini? Jika iya, lebih aman rollback aplikasi saja dan biarkan skema tetap. Jika tidak kompatibel, berarti masalahnya ada pada desain migration sebelumnya.
Hal yang sering terlupa saat rollback
- Cache konfigurasi atau route yang belum diperbarui.
- Supervisor/worker queue masih memakai kode lama atau environment lama.
- Job tertunda yang membawa payload dari versi baru lalu diproses oleh worker versi lama.
- Feature flag aktif di sebagian instance saja.
Contoh verifikasi pascadeploy
Verifikasi pascadeploy sebaiknya singkat tetapi sistematis. Anda tidak perlu menguji semua fitur, cukup jalur paling kritis.
- Cek endpoint health dan identitas release.
- Uji satu alur utama: login, baca data, tulis data, dan proses async jika ada.
- Pastikan log tidak menunjukkan exception baru yang konsisten.
- Bandingkan latency endpoint utama terhadap baseline sebelum deploy.
- Periksa queue backlog dan failed jobs.
- Pastikan alarm tidak diam-diam dimatikan atau di-silence terlalu lama.
Feature toggle dan backward-compatible change untuk mencegah insiden berulang
Feature toggle
Feature toggle memisahkan deploy dari release. Ini berguna jika kode harus masuk dulu, tetapi fitur hanya diaktifkan untuk sebagian pengguna atau setelah observasi tertentu.
Gunakan toggle terutama untuk:
- fitur yang mengubah alur bisnis penting,
- integrasi baru ke layanan eksternal,
- query atau cache strategy baru,
- perubahan perilaku yang sulit dibatalkan dengan cepat.
Trade-off-nya: terlalu banyak toggle membuat codebase sulit dipahami. Bersihkan toggle yang sudah permanen agar tidak menjadi utang teknis.
Backward-compatible change
Setiap perubahan yang menyentuh kontrak antar komponen sebaiknya kompatibel maju dan mundur selama masa transisi:
- payload job queue,
- format event,
- skema database,
- respons API internal,
- cache key atau struktur cache.
Jika stable dan canary hidup bersamaan, anggap sistem Anda sedang dalam keadaan mixed version. Semua perubahan harus aman pada kondisi ini.
Alarm dan runbook yang benar-benar dipakai
Alarm tidak perlu banyak, tetapi harus relevan dan bisa ditindaklanjuti. Minimal buat alarm untuk:
- lonjakan 5xx,
- latency endpoint kritis meningkat,
- failed jobs atau backlog queue meningkat,
- readiness gagal pada banyak instance.
Setiap alarm sebaiknya punya runbook singkat berisi:
- apa arti alarm tersebut,
- metrik pembanding yang harus dicek,
- langkah mitigasi pertama,
- kapan harus rollback,
- siapa yang perlu diberi tahu.
Runbook yang baik mengurangi keputusan panik saat insiden. Tujuannya bukan dokumen panjang, melainkan petunjuk cepat yang bisa dijalankan dalam menit pertama.
Postmortem ringan setelah insiden rilis
Jika canary gagal dan rollback dilakukan, jangan berhenti di “sudah normal lagi”. Buat postmortem ringan agar insiden serupa tidak terulang.
Template sederhana postmortem
- Ringkasan: apa yang terjadi dan kapan.
- Dampak: endpoint/fitur terdampak, durasi, dan siapa yang terpengaruh.
- Deteksi: alarm atau sinyal apa yang pertama kali muncul.
- Timeline: deploy, muncul anomali, mitigasi, rollback, pulih.
- Akar masalah teknis: misalnya migration tidak kompatibel, query baru lambat, payload job berubah, atau dependency eksternal gagal ditangani dengan baik.
- Yang berjalan baik: misalnya canary menahan dampak hanya pada sebagian kecil trafik.
- Yang perlu diperbaiki: test, observability, alarm, runbook, desain data, atau toggle.
- Action item: tugas konkret dengan pemilik dan target waktu.
Contoh action item yang berkualitas
- Tambahkan alarm untuk failed jobs berdasarkan release.
- Ubah migration berikutnya ke pola expand-and-contract.
- Tambahkan verifikasi pascadeploy untuk endpoint pembayaran.
- Buat toggle untuk integrasi baru agar bisa dimatikan tanpa rollback total.
- Perbarui runbook rollback worker queue.
Hindari postmortem yang hanya menyalahkan individu. Fokus pada perbaikan sistem: deteksi lebih cepat, keputusan lebih jelas, dan desain perubahan yang lebih aman.
Kesalahan umum saat menerapkan canary deploy di Laravel
- Menganggap health check saja cukup untuk menyatakan deploy aman.
- Tidak membedakan metrik stable dan canary.
- Melupakan worker queue dalam proses deploy dan rollback.
- Menjalankan migration yang tidak backward-compatible.
- Tidak punya release identifier di log.
- Tidak menyiapkan feature toggle untuk fitur berisiko tinggi.
- Tidak melakukan verifikasi pascadeploy setelah 100% rollout.
Penutup
Laravel: Canary Deploy dengan SLO, Rollback, dan Postmortem Ringan pada dasarnya adalah soal disiplin operasional: rilis bertahap, ukur dampaknya, lalu putuskan berdasarkan data. Untuk mulai, Anda tidak perlu platform observability yang kompleks. Cukup siapkan health check yang benar, log terstruktur, metrik minimum, migration yang kompatibel, checklist rollback, dan kebiasaan postmortem setelah insiden.
Jika dilakukan konsisten, canary deploy bukan hanya mengurangi risiko rilis, tetapi juga memaksa tim membangun aplikasi Laravel yang lebih siap menghadapi perubahan di produksi.
Komentar
0 komentar
Masuk ke akun kamu untuk ikut berkomentar.
Belum ada komentar
Jadilah yang pertama ikut berdiskusi!