Cerita migrasi ini dimulai bahkan sebelum saya resmi bekerja.
Di sebuah perusahaan GPS tracking di Surabaya, salah satu senior tim mendapat mandat me-rewrite sistem eksisting. Sampai hari ini saya tidak tahu persis apa yang dibicarakan di rapat internalnya; yang saya tahu hanya hasilnya: mereka memutuskan pindah ke Go. Dan baru setelah keputusan itu mantap, lowongan pun dibuka.
Jadi posisi saya di rekrutmen itu agak unik: saya bukan ikut menentukan arah proyeknya. Saya datang untuk menjalankan keputusan yang sudah dibuat orang lain.
Di interview, pertanyaan utamanya wajar: bisa tidak, me-migrasi Laravel ke Go? Sempat ada tawaran tes, semacam “nanti kami tunjukkan contoh aplikasi kami, coba kerjakan dalam seminggu”. Tawaran itu akhirnya tidak jadi. Ya sudah, interview berjalan seperti biasa, dan saya diterima.
Nah, ada satu kesepakatan yang ternyata sudah menunggu saya sejak sebelum hari pertama (entah lahir kapan): para pengambil keputusan sepakat proyek migrasi ini harus tuntas develop plus testing dalam tiga bulan.
Tiga bulan. Untuk 370+ endpoint.1 Ehem.
Angkanya lahir dari keyakinan yang kedengarannya masuk akal di rapat: migrasi Laravel ke Go itu cepat dan mudah, tinggal pindahin, langsung siap pakai di production. Cukup export-import, kan? Yang belum sempat ditanyakan: kenapa satu-satunya orang di rapat yang paham pekerjaannya, yang tugasnya cukup mengiyakan, tidak menyela dengan satu kalimat: “sebentar, ini beda kategori”.
Kalau dihitung, sekitar empat endpoint per hari, tujuh hari seminggu, tanpa akhir pekan atau libur nasional. Waktu untuk bertanya “kok bisa ya semantap itu menetapkan angkanya?” juga tidak masuk hitungan. Cantik di slide, kurang cantik di keyboard.
Ini episode pertama seri Hijrah Backend, catatan saya tentang memindahkan backend GPS dari PHP ke Go. Tenggat aslinya sudah lama lewat. Versi teknisnya (kenapa Go, pendekatannya, dan apa yang saya pelajari) sudah saya tulis di tulisan April kemarin. Di seri ini saya cerita hal-hal yang tidak muat di catatan teknis: keputusan, kekeliruan, dan orang-orang di balik migrasinya.
Struktur Pasukan (dan Proporsinya) #
Awal 2025, tim IT terbagi tiga: dua rekan merawat aplikasi eksisting, dua lagi membangun backoffice admin, dan satu sub-tim khusus migrasi. Sub-tim migrasi isinya dua orang: satu senior pemegang mandat, dan satu saya.
Pembagian kerjanya ya… kurang seimbang.
Praktiknya, semua kode Go yang saya ceritakan di seri ini saya tulis sendiri. Kontribusi sang pemegang mandat lebih banyak berupa pertanyaan: “kok error?”, “kok responsnya beda?”, “kok makin lemot? Go kan katanya lebih cepat?” Semuanya sah sebagai feedback. Hanya saja, yang bertanya bukan yang membuka editor.
Waktu isu kecepatan itu ramai, saya sempat menimpali dengan catatan teknis: menyebutnya “migrasi Laravel ke Go” sebenarnya tidak apple to apple. Laravel itu framework, Go itu bahasa. Mau adil membandingkan framework? Bandingkan Laravel dengan CodeIgniter. Mau adil membandingkan bahasa? Bandingkan PHP native dengan Go native. Yang terjadi di mandat kami: bahasanya diambil dari satu sisi, framework-nya dari sisi lain, lalu kecepatannya ditagih hehe.
Warisan yang Diterima #
Sistem yang saya terima ternyata dua dunia PHP yang hidup berdampingan.
Dunia pertama: API Laravel 8 dengan sekitar 290 endpoint, jadi 370+ kalau cron job ikut dihitung.1 Dunia kedua: aplikasi CodeIgniter 3 yang jadi pintu masuk data, TCP listener yang menerima paket dari puluhan tipe GPS tracker (Teltonika, GT06, JT808, dan puluhan kerabatnya), ditambah 100-an cron job yang mengolah data itu tiap malam.
Datanya juga tidak main-main. Puluhan ribu unit GPS live tracking, puluhan juta baris data lokasi dan alert, semuanya masuk ke MySQL.
Gejalanya sudah kelihatan sejak minggu-minggu awal. Di halaman dashboard estimasi bahan bakar per grup kendaraan, misalnya, 30 kendaraan memicu ratusan query: ambil device, ambil tipe device-nya, lalu loop tujuh hari untuk ringkasan harian. Database-nya kerja rodi, user-nya menunggu sambil ngopi.
Ada juga endpoint yang bisa makan 15 detik sekali panggil. Saya sempat menyalahkan beberapa hal sebelum ketemu penyebabnya. Ceritanya ada di episode berikutnya.
Godaan Rewrite Total #
Dengan warisan segitu, godaan pertama terasa manis: “rewrite semuanya dari nol aja. Bersih, modern, enak dibaca.”
Amit-amit. Jujur, saya sempat tergiur sebentar. Tapi rewrite total itu berarti berjudi dengan perilaku sistem yang selama ini dipercaya puluhan ribu user. Perilakunya kadang aneh, kadang tidak terdokumentasi, tapi sudah jadi kenyataan sehari-hari mereka.
Jadi saya pilih jalan yang kurang glamor: parity-first, kode lama diperlakukan sebagai executable spec. Endpoint baru di Go harus berperilaku identik dengan yang lama, quirk-nya juga. Kecuali quirk yang jelas-jelas tidak dipakai frontend, itu dibersihkan sambil mikir dua kali. Pelan-pelan, satu endpoint per satu waktu, sementara sistem lama tetap melayani. Business as usual, gitu loh.
Keputusan ini yang menentukan arah semua episode berikutnya. Kenapa parity-first justru menghemat banyak waktu (plus contoh quirk yang bikin saya garuk-garuk kepala) saya bahas di episode keempat.
Peta Perjalanan #
Seri ini isinya delapan episode plus satu epilog. Kalau kamu baca ini dan episode selanjutnya sudah terbit, berarti semuanya tayang serentak sesuai rencana hehe:
- Anatomi endpoint 15 detik: empat hipotesis salah dulu, baru penyebab aslinya ketemu di tempat yang sama sekali tidak terduga.
- Mem-port puluhan parser protokol GPS: mengganti kode pembaca paket biner dari berbagai merek tracker, tanpa merusak data armada yang sudah jalan.
- Kode lama sebagai executable spec: parity-first lebih dalam, apa yang harus identik dan apa yang boleh dibuang.
- Query yang bilang “pakai index-ku”: pelajaran sargable di tabel puluhan juta baris.
- Merapikan monolith jadi 14 modul domain: restrukturisasi sambil pesawatnya terbang.
- Dari paket TCP ke time-series database: perjalanan data lokasi dari listener sampai tersimpan rapi.
- Refleksi 18 bulan: apa yang akan saya lakukan beda kalau mengulang, plus rencana mengajar Go yang masih menunggu jadwal hehe.
- Epilog: MySQL, PostgreSQL, lalu MySQL lagi: kisah mesin database yang pindah haluan dua kali, dan siapa yang bayar ongkosnya.
Penutup #
Mandat itu memberi saya tiga bulan. Waktu tulisan ini dibuat, migrasinya sudah jauh melewati tenggat tersebut. Jarak antara angka di slide dan kenyataan di keyboard saya lalui dengan bantuan Allah, doa keluarga, dan dukungan istri. Tanpa mereka, catatan ini tidak akan ada.
Episode kedua kembali ke endpoint 15 detik tadi. Spoiler: masalahnya bukan di query yang saya curigai.
Kalau kamu cari tutorial membangun backend GPS dari nol, saya menulisnya terpisah di seri GPS Backend. Seri Hijrah ini catatan di balik pekerjaan itu.
Terima kasih sudah membaca!
-
Sekitar 290 endpoint API di Laravel, plus 100-an cron job dan endpoint di aplikasi CodeIgniter 3. Angka “370+” yang saya pakai di tulisan April berasal dari jumlahan keduanya. ↩︎ ↩︎