Aplikasi Laravel yang sudah masuk production biasanya tidak rusak karena satu kesalahan besar. Lebih sering, masalah muncul dari hal kecil yang dibiarkan menumpuk: queue mulai tertahan, log penuh error yang tidak dibaca, scheduler diam-diam berhenti, atau dependency dinaikkan tanpa pengujian yang cukup.
Maintenance bukan pekerjaan yang dilakukan saat aplikasi sudah lambat atau server sudah merah. Lebih aman kalau ia dijadikan pola kerja rutin. Tujuannya sederhana: aplikasi tetap mudah dipantau, perubahan tetap terkendali, dan saat insiden datang tim tidak mulai dari nol.

Mulai dari ritme maintenance yang realistis
Kesalahan yang cukup umum adalah membuat checklist terlalu panjang, lalu tidak ada yang benar-benar menjalankannya. Lebih baik bagi pekerjaan berdasarkan frekuensi dan buat yang penting mudah dilakukan.
- Harian: cek error baru, status queue, job gagal, kapasitas disk, dan indikator aplikasi utama.
- Mingguan: baca tren performa, bersihkan backlog yang aneh, tinjau log penting, serta cek hasil backup.
- Bulanan: audit dependency, patch keamanan, review akses, uji restore backup, dan evaluasi biaya infrastruktur.
- Setiap rilis: jalankan test, migration review, cache strategy, smoke test, serta siapkan rollback.
Ritme ini tidak harus dilakukan manual semua. Yang berulang sebaiknya dijadikan monitoring atau job terjadwal. Manual tetap diperlukan untuk hal yang butuh penilaian, misalnya membaca pola error atau memutuskan apakah sebuah package aman dinaikkan versinya.

Jaga observability sebelum bicara optimasi
Kalau aplikasi lambat tetapi tim tidak tahu endpoint mana yang lambat, query mana yang berat, atau job mana yang menumpuk, proses perbaikannya akan jadi tebak-tebakan. Di Laravel, log bawaan memang berguna, tetapi production biasanya butuh lebih dari file laravel.log.
Minimal, pisahkan tiga jenis sinyal: error aplikasi, performa request, dan kesehatan worker. Error bisa masuk ke layanan pelacakan seperti Sentry atau Bugsnag. Performa request dan query perlu dipantau lewat APM atau metrik server. Untuk queue, gunakan Horizon jika memakai Redis queue, atau dashboard yang setara untuk driver lain.
Log harus bisa ditindaklanjuti
Log yang baik menjawab pertanyaan dasar saat ada insiden: siapa yang terdampak, request apa yang gagal, kapan mulai terjadi, dan apa konteksnya. Simpan correlation ID atau request ID bila aplikasi punya beberapa service. Jangan pernah memasukkan password, token, nomor kartu, atau payload sensitif mentah ke log. Ini sering luput ketika mode debug dipakai terlalu lama.
Catatan kecil dari kasus lapangan: error berulang dengan level warning kadang lebih berbahaya daripada satu exception besar. Exception besar biasanya cepat terlihat. Warning kecil, seperti retry job yang terus gagal, bisa menghabiskan worker dan baru terasa ketika antrean transaksi mulai telat diproses.
Rawat queue dan scheduler seperti komponen inti
Banyak fitur Laravel berjalan di belakang layar: kirim email, sinkronisasi data, generate laporan, webhook, impor file, sampai notifikasi. Kalau queue macet, halaman utama mungkin masih terlihat normal, tetapi proses bisnisnya sudah tidak sehat.
Pastikan worker dikelola oleh process manager seperti Supervisor atau systemd, lalu di-restart secara aman setelah deployment. Untuk worker yang berjalan lama, gunakan batas memori dan waktu kerja yang masuk akal. Worker PHP tidak selalu bersih dari memory leak, terutama bila job memproses file besar atau memakai library pihak ketiga.
- Tentukan
timeoutdantriesberdasarkan jenis job, bukan disamaratakan. - Gunakan retry dengan jeda atau backoff agar kegagalan API pihak ketiga tidak memukul sistem terus-menerus.
- Siapkan jalur penanganan untuk failed jobs. Jangan hanya menyimpan tabel
failed_jobslalu lupa membukanya. - Buat job idempotent jika memungkinkan. Job yang dijalankan dua kali tidak boleh menggandakan invoice, saldo, atau email penting.
Untuk scheduler, cek bukan cuma apakah php artisan schedule:run dipanggil oleh cron, tetapi juga apakah task yang dijadwalkan benar-benar selesai. Gunakan withoutOverlapping() untuk proses yang tidak boleh paralel, dan beri alert jika task penting tidak berjalan dalam periode tertentu.
Database: jangan menunggu CPU melonjak
Masalah database Laravel sering muncul pelan-pelan. Awalnya hanya satu halaman admin yang terasa lebih lambat. Beberapa bulan kemudian, query yang sama dipanggil ribuan kali per menit dan database mulai jadi titik sempit.
Review query pada fitur yang ramai dipakai. Cari pola N+1 query, pagination yang terlalu mahal, penggunaan LIKE %kata% pada tabel besar, serta query tanpa indeks pada kolom filter atau join. Laravel Eloquent nyaman dipakai, tetapi kemudahan itu kadang menyembunyikan jumlah query yang sebenarnya terjadi.
Migration perlu perlakuan khusus
Migration di production bukan sekadar menjalankan php artisan migrate --force. Pada tabel besar, menambah indeks atau mengubah kolom bisa mengunci tabel dan mengganggu request aktif. Rancang perubahan schema secara bertahap: tambahkan kolom nullable dulu, deploy kode yang bisa membaca kondisi lama dan baru, isi data secara batch, lalu rapikan constraint di rilis berikutnya.
Prinsipnya, migration harus kompatibel dengan aplikasi versi sebelum dan sesudah deploy. Ini penting kalau deployment memakai beberapa instance yang tidak berpindah versi dalam detik yang sama.
Cache itu membantu, tapi harus punya aturan invalidasi
Cache bisa menurunkan beban database dengan drastis, tetapi juga bisa membuat data terlihat salah jika invalidasinya asal. Hindari cache permanen tanpa alasan yang jelas. Tentukan data apa yang boleh stale, berapa lama, dan peristiwa apa yang wajib menghapus cache.
Untuk konfigurasi Laravel, optimasi seperti config:cache, route:cache, dan view:cache masuk akal saat deploy. Namun, jangan menjalankannya sembarangan pada environment yang masih berubah-ubah. Pastikan semua environment variable yang dibutuhkan sudah benar sebelum config cache dibuat.
Sesudah deploy, lakukan smoke test pada fitur paling penting. Pernah ada kasus route sudah benar di lokal, tetapi production menyimpan route cache lama karena urutan perintah deploy keliru. Secara teknis deploy sukses, tetapi endpoint baru memberi 404. Ini jenis masalah yang murah dicegah dengan satu atau dua request pengecekan.
Dependency dan patch keamanan perlu jadwal
Jangan menunggu upgrade framework besar untuk memperbarui dependency. Update kecil yang rutin lebih mudah ditelusuri dibanding lompat beberapa versi sekaligus setelah setahun. Simpan composer.lock di repository agar build antar-server konsisten.
Sebelum update package, baca changelog untuk perubahan yang menyentuh autentikasi, filesystem, queue, database, atau serialisasi. Jalankan test suite, lalu uji alur inti di staging. Untuk kerentanan yang mendesak, patch tetap perlu cepat, tetapi bukan berarti langsung deploy tanpa validasi dasar.
Mode debug juga wajib diperiksa. APP_DEBUG=true di production dapat membocorkan konfigurasi, path server, dan detail exception. Pastikan ini masuk pemeriksaan deployment, bukan hanya mengandalkan ingatan.
Backup baru berguna kalau restore pernah diuji
Backup database dan file upload harus otomatis, terenkripsi bila diperlukan, serta disimpan di lokasi terpisah dari server aplikasi. Namun bagian paling penting sering terlewat: uji restore. Backup yang terlihat berhasil belum tentu dapat dipulihkan saat dibutuhkan.
Lakukan simulasi restore secara berkala ke environment terisolasi. Ukur berapa lama prosesnya, cek integritas data, dan pastikan file yang diperlukan ikut tersedia. Dari sini tim bisa tahu nilai RTO yang realistis, bukan sekadar asumsi di dokumen.
Deploy harus bisa dibatalkan dengan tenang
Deployment sehat adalah deployment yang punya jalan mundur. Siapkan artefak rilis yang jelas, catat versi yang sedang aktif, dan hindari perubahan langsung di server production. Jika memungkinkan, gunakan deployment atomik dengan symlink release agar perpindahan versi cepat dan rollback lebih sederhana.
- Jalankan test otomatis dan build dependency dari versi yang terkunci.
- Review migration, terutama yang menyentuh tabel besar atau data transaksi.
- Deploy aplikasi, refresh cache sesuai urutan yang aman, lalu restart worker queue.
- Lakukan smoke test pada login, transaksi utama, endpoint API penting, dan proses background.
- Pantau error rate serta queue selama beberapa menit pertama setelah rilis.
Rollback kode tidak selalu membatalkan perubahan database. Karena itu migration destruktif perlu dihindari dalam satu langkah rilis. Pisahkan perubahan schema dan penghapusan kolom lama agar rollback tetap masuk akal.
Checklist sederhana yang benar-benar dipakai
Maintenance Laravel yang sehat tidak harus bergantung pada dokumen tebal. Mulai dengan checklist singkat yang hidup: status backup, failed jobs, error baru, kapasitas disk, versi dependency penting, dan hasil smoke test rilis terakhir. Tinjau setelah ada insiden. Kalau suatu poin terbukti tidak membantu, buang. Kalau insiden menemukan celah baru, tambahkan.
Pada akhirnya, aplikasi production yang stabil bukan aplikasi tanpa error. Itu hampir tidak ada. Yang membedakan adalah seberapa cepat tim melihat gejalanya, seberapa aman perubahan dilakukan, dan seberapa siap sistem dipulihkan ketika sesuatu benar-benar gagal.