Banyak perusahaan di Indonesia menjalankan operasional hariannya di sistem yang dibuat sepuluh atau lima belas tahun lalu. Stok, invoice, payroll, kadang seluruh alur pesanan. Sistemnya masih jalan, staf sudah hafal keanehannya, dan tidak ada yang berani menyentuhnya. Lalu ada kejadian yang memaksa: PC server di bawah meja mulai berbunyi aneh, audit IT dari klien menandai PHP 5, atau satu-satunya orang yang paham kodenya resign. Reaksi pertama biasanya ingin membangun ulang semuanya dari nol. Dari pengalaman kami, itu sering jadi pilihan paling mahal dan jarang jadi yang paling aman.
Wujud Aplikasi Legacy yang Sering Kami Temui
Kasus paling umum: aplikasi web PHP native atau CodeIgniter 2 buatan sekitar 2012, tabel MySQL dengan engine MyISAM, dan query SQL yang dirangkai dari potongan string. Jalannya di PC yang dijadikan server, ditaruh di bawah meja gudang, dengan CentOS 6 atau Windows Server 2008. Kasus kedua: aplikasi desktop Visual Basic 6 atau Delphi 7 yang di-install di setiap PC kasir atau admin, tersambung ke file Access di shared folder atau ke SQL Server 2008.
Developernya dulu freelancer atau karyawan yang sudah lama keluar. Source code-nya ada di server, di satu laptop tua, atau malah tidak ada. Dokumentasi nihil, dan aturan bisnisnya cuma tersimpan di kode dan di kepala dua staf senior. Semua itu tidak berarti sistemnya jelek. Sistem itu menghidupi bisnis selama sepuluh tahun, sesuatu yang tidak semua sistem baru sanggup lakukan.
Tanda Sudah Waktunya Bertindak
- Patch keamanan sudah berhenti. PHP 5.6 tidak lagi mendapat patch sejak akhir 2018, CodeIgniter 2 sejak 2015, SQL Server 2008 sejak Juli 2019, dan CentOS 6 sejak 2020. Aplikasi di stack seperti itu yang terbuka ke internet sama saja dengan pintu tidak dikunci.
- Cuma satu orang yang paham, sering mantan karyawan yang dibayar per kunjungan dan makin susah dihubungi.
- Tidak bisa rekrut. Developer muda di Bandung atau Jogja menguasai Laravel, Go, atau Flutter. Jarang sekali yang mau belajar VB6 atau CodeIgniter 2.
- Tidak bisa diintegrasikan. Menyambungkan ke Shopee, Tokopedia, atau TikTok Shop, ke Midtrans, ke WhatsApp Business API, atau ke Accurate dan Jurnal jadi repot atau mustahil, dan server lama kadang tidak sanggup membuka koneksi TLS modern.
- Setiap perubahan butuh berminggu-minggu dan merusak bagian lain, sampai bisnis berhenti meminta perubahan.
Satu tanda saja jarang cukup jadi alasan untuk rewrite. Kode yang jelek bahkan tidak masuk daftar. Kalau sistemnya jalan, tidak ada yang butuh perubahan, dan tidak terbuka ke internet, jawaban jujurnya bisa jadi biarkan saja: pindahkan ke virtual machine dengan OS yang masih didukung, pasang backup yang benar, dan pakai anggarannya untuk hal lain. Keputusan seperti itu tidak perlu software house.
Langkah Awal Sebelum Memutuskan Apa Pun
Apa pun pilihannya nanti, minggu-minggu pertamanya sama. Backup sistemnya dengan benar: dump database, source code, file konfigurasi, jadwal task, dan kalau bisa image dari seluruh server. Setelah itu restore di mesin lain dan pastikan jalan. Backup yang belum pernah di-restore itu baru harapan. Soal ini kami bahas lebih lengkap di artikel tentang backup dan disaster recovery.
Berikutnya, masukkan kode ke Git persis seperti yang berjalan di production, termasuk hotfix yang dulu diedit langsung di server tahun 2019. Bandingkan dengan salinan di laptop-laptop sebelum salinan itu dibuang. Lalu buat inventaris: modul yang masih dipakai, pengguna dan role, cron job dan Windows scheduled task, semua integrasi, serta laporan yang benar-benar dibuka tim finance dan operasional di akhir bulan. Biasanya ada modul yang ternyata sudah tidak dipakai. Itu penghematan gratis.
Dokumentasikan model datanya dari database yang asli, bukan dari ingatan. Tandai tabel mana yang masih ditulisi, dan catat arti nilai-nilai ajaibnya, misalnya status 3 berarti sudah di-approve manajer tapi belum dikirim. Terakhir, tulis characterisation test. Test ini merekam perilaku sistem hari ini, bukan perilaku yang seharusnya. Masukkan input yang sudah diketahui ke perhitungan invoice dan simpan output-nya, lengkap dengan keanehan pembulatannya. Ekspor laporan bulan lalu dan simpan sebagai pembanding. Dengan PHPUnit untuk logika dan Playwright untuk layar-layar utama, test ini jadi jaring pengaman untuk pilihan mana pun di bawah.
Pilihannya, dari yang Paling Ringan
Pertahankan dan stabilkan artinya membereskan risiko operasional tanpa banyak mengubah kode: server atau VM yang layak, backup yang sudah diuji, monitoring uptime, akses lewat VPN alih-alih terbuka ke internet, dan perbaikan lubang terparah seperti SQL injection di form login. Rehost atau lift and shift memindahkan kode yang sama dari PC di bawah meja ke VM di data center Jakarta atau ke penyedia cloud. Risiko hardware hilang, tapi runtime lamanya tetap ada, jadi jangan buka ke internet publik.
Upgrade di tempat berarti aplikasinya tetap, runtime-nya yang dinaikkan ke versi yang masih didukung. Untuk PHP biasanya bertahap dari 5.6 ke 7.4 lalu ke 8.x. Pekerjaan terbesarnya mengganti fungsi mysql_* yang sudah dihapus sejak PHP 7.0. Rector mengotomatiskan banyak perubahan sintaks, dan PHPCompatibility untuk PHP_CodeSniffer menemukan sisanya. CodeIgniter 2 ke 3 punya panduan upgrade resmi. CodeIgniter 3 ke 4 lebih mirip porting daripada upgrade. Kode Delphi bisa dipindah ke versi Delphi terbaru, tapi peralihan ke string Unicode di Delphi 2009 membuat kode lama butuh usaha yang tidak sedikit. VB6 praktis tidak punya jalur upgrade.
Refactor bertahap memperbaiki struktur sedikit demi sedikit, dijaga characterisation test, sambil tim tetap merilis fitur. Strangler fig pattern selangkah lebih jauh: modul baru dibangun di samping sistem lama, satu fungsi demi satu fungsi dialihkan ke kode baru, dan bagian lama dimatikan setelah yang baru terbukti jalan. Pola ini sudah kami bahas panjang di artikel monolith vs microservices. Rewrite total membangun pengganti dari nol, lalu pindah sekaligus saat sudah siap.
Perbandingan Pilihan Modernisasi
Angka di bawah adalah kisaran indikatif untuk sistem bisnis ukuran menengah dengan beberapa puluh layar. Angkanya sangat bervariasi tergantung besar codebase dan kondisi datanya, jadi pakai untuk membandingkan pilihan, bukan sebagai penawaran harga.
| Pilihan | Biaya indikatif | Risiko | Durasi umum | Cocok kalau |
|---|---|---|---|---|
| Pertahankan dan stabilkan | Rp15 juta sampai Rp60 juta | Rendah | 2 sampai 6 minggu | Sistemnya jalan, jarang berubah, dan risiko utamanya hardware, backup, dan akses dari luar |
| Rehost (lift and shift) | Rp10 juta sampai Rp50 juta ditambah biaya hosting | Rendah | 1 sampai 4 minggu | Masalahnya lebih di server daripada di kode |
| Upgrade di tempat | Rp40 juta sampai Rp250 juta | Sedang | 1 sampai 4 bulan | Kodenya masih layak tapi runtime atau framework-nya sudah tidak didukung |
| Refactor bertahap | Bagian dari anggaran maintenance bulanan | Rendah sampai sedang | Berkelanjutan | Sistem masih sering berubah dan tidak boleh berhenti |
| Strangler fig | Mulai Rp200 juta, tersebar sepanjang waktu | Sedang | 6 sampai 18 bulan | Sebagian modul butuh kemampuan baru, sebagian lain cukup dibiarkan |
| Rewrite total | Mendekati biaya membangun baru, sering Rp300 juta sampai beberapa miliar | Tinggi | 6 sampai 24 bulan | Platformnya sudah mati (VB6 yang harus jadi web atau mobile), atau sistemnya kecil dan dipahami dengan baik |
Kenapa Rewrite Sekaligus Sering Gagal
Penyebab pertama adalah aturan bisnis yang tersembunyi. Di suatu tempat di kode lama ada if yang memberi diskon khusus untuk pelanggan nomor 117, aturan pembulatan pembayaran tunai ke Rp100 terdekat, dan laporan yang tidak menghitung retur setelah tanggal 25. Tidak ada yang menyebutnya di rapat requirement karena memang tidak ada yang ingat. Aturan-aturan itu baru muncul saat finance tutup buku bulan pertama di sistem baru dan angkanya tidak cocok.
Penyebab kedua, scope melebar. Begitu rewrite diumumkan, setiap divisi menitipkan keinginan yang sudah lama dipendam, dan penggantinya berubah jadi sistem baru dengan desain dan proses baru. Ketiga, sistem lama terus berubah. Selama rewrite dua belas bulan, bisnis tetap butuh aturan diskon baru, daftar harga baru, dan laporan baru, jadi tim membangunnya dua kali atau sistem baru sudah ketinggalan di hari pertama. Rewrite juga baru menghasilkan sesuatu di akhir. Kalau anggaran dipotong di tengah jalan, Anda punya dua sistem yang sama-sama setengah jadi.
Kode lama memang jelek, tapi cuma kode itu yang mencatat lengkap bagaimana bisnis Anda sebenarnya berjalan.
Migrasi Data dan Parallel Run
Jadwal biasanya molor di migrasi data. Data lama itu kotor: pelanggan dobel dengan nama yang sedikit beda, tanggal yang disimpan sebagai teks bebas, tabel latin1 yang hurufnya rusak, database Access tanpa foreign key, dan tiga cara berbeda untuk menandai baris yang dihapus. Tulis migrasinya sebagai script yang bisa dijalankan ulang, jalankan berkali-kali ke salinan production yang baru, dan rekonsiliasi totalnya setiap kali. Jumlah baris saja tidak cukup. Bandingkan piutang per pelanggan dan stok per barang per gudang.
Untuk apa pun yang menyangkut uang atau stok, jalankan kedua sistem bersamaan selama satu siklus penuh, biasanya satu kali tutup buku akhir bulan, lalu bandingkan hasilnya. Input ganda memakan waktu staf, jadi buat sesingkat mungkin atau isi sistem baru otomatis dari sistem lama. Tentukan tanggal cutover bersama tim operasional, dan jangan pernah menjelang Lebaran atau saat tutup buku akhir tahun. Biarkan sistem lama tetap bisa dibuka dalam mode read-only minimal setahun, karena pasti ada yang perlu mencari transaksi lama.
Urutan Kerja yang Masuk Akal
- 1Backup database, kode, konfigurasi, dan server, lalu buktikan backup-nya dengan restore di mesin lain.
- 2Masukkan kode production ke Git persis seperti yang berjalan hari ini.
- 3Inventaris modul, pengguna, job terjadwal, integrasi, laporan, dan server-nya sendiri, lalu tandai yang sudah tidak dipakai.
- 4Dokumentasikan model data dan arti setiap kode status dan flag.
- 5Tulis characterisation test untuk perhitungan dan laporan yang diandalkan tim finance dan operasional.
- 6Stabilkan: hosting yang masih didukung, monitoring, akses lewat VPN, dan perbaikan lubang keamanan terparah.
- 7Putuskan per modul: dibiarkan, di-upgrade, di-refactor, atau diganti, lalu hitung ulang estimasinya dengan informasi yang sekarang sudah Anda punya.
- 8Migrasikan data dengan script yang bisa diulang, jalankan paralel satu siklus penuh, dan cutover di luar periode sibuk.
Pendapat kami, setelah cukup banyak mengambil alih sistem seperti ini, kebanyakan cuma butuh distabilkan dan di-upgrade, bukan ditulis ulang. Rewrite masuk akal untuk bagian yang benar-benar menghambat bisnis, dan pendekatan strangler memungkinkan bagian itu diganti satu per satu. Saat kami menangani sistem legacy, dua sampai empat minggu pertama diisi backup, Git, inventaris, dan test seperti di atas. Baru setelah itu kami berani menyebut angka untuk pilihan yang lebih besar.
Poin penting
- Sistem lama yang masih jalan dan tidak terbuka ke internet mungkin cuma butuh server yang didukung dan backup yang sudah diuji.
- Sebelum memutuskan apa pun, backup, masukkan ke Git, buat inventaris, dokumentasikan model data, dan tulis characterisation test.
- Upgrade di tempat, misalnya PHP 5.6 ke 8.x dengan bantuan Rector, sering jauh lebih murah daripada rewrite dan aturan bisnis tersembunyinya tetap utuh.
- Rewrite sekaligus sering gagal karena aturan tersembunyi, scope yang melebar, dan sistem lama yang terus berubah, jadi ganti per modul kalau bisa.
- Migrasikan data dengan script yang bisa diulang, cocokkan totalnya, jalankan paralel satu kali tutup buku, dan hindari cutover menjelang Lebaran atau akhir tahun.


