Kalau pengguna Anda bekerja di daerah dengan sinyal tidak menentu, offline-first bukan fitur tambahan — itu produknya. Ini pendekatan kami dengan Flutter dan SQLite.
Pada 2021, kami membangun sistem manajemen perumahan untuk program perumahan pemerintah di beberapa wilayah di Indonesia. Tantangannya terdengar sederhana di atas kertas: mengelola pengajuan sewa, melacak unit, dan membuat laporan hunian.
Bagian sulitnya? Petugas lapangan sering bekerja di lokasi tanpa sinyal data yang bisa diandalkan. Aplikasi yang hanya jalan saat online tidak akan berguna bagi mereka.
Kenapa Offline-First Mengubah Segalanya
Kebanyakan aplikasi memperlakukan kondisi offline sebagai kasus pinggiran — penurunan fungsi yang "sopan" saat jaringan putus. Offline-first membalik logika itu: perangkat lokal adalah sumber kebenaran utama, dan server adalah tujuan sinkronisasi.
Ini mengubah cara Anda memikirkan hampir setiap bagian sistem:
- Pembacaan data diambil dari penyimpanan lokal lebih dulu
- Penulisan masuk ke antrean lokal, bukan langsung ke server
- Penyelesaian konflik jadi perkara utama, bukan pelengkap
- Sinkronisasi adalah proses latar belakang, bukan operasi yang memblokir
Pilihan Teknologi Kami
Flutter jadi pilihan alami untuk klien mobile. Satu basis kode untuk Android (platform utama petugas lapangan), dengan jalur yang bersih ke iOS bila nanti dibutuhkan. Sistem widget Flutter memudahkan pembuatan antarmuka padat data yang tetap nyaman di perangkat Android kelas menengah.
SQLite (lewat paket sqflite) menangani penyimpanan lokal. Kami merancang skema lokal agar sedekat mungkin dengan skema server, dan itu menyederhanakan logika sinkronisasi secara signifikan.
Go menjalankan API backend. Model konkurensinya sanggup menangani lonjakan permintaan sinkronisasi — saat banyak perangkat kembali online setelah lama bekerja offline — tanpa masalah performa.
Strategi Sinkronisasi
Kami memakai pendekatan sinkronisasi berbasis timestamp dengan change log di sisi server:
- Setiap record punya timestamp
updated_at, baik di klien maupun server - Saat sinkronisasi, klien mengirim timestamp sinkronisasi terakhirnya
- Server mengembalikan semua record yang berubah sejak timestamp tersebut
- Klien menggabungkannya, dengan record server yang menang bila terjadi konflik (last-write-wins)
- Klien mengirim antrean penulisan lokal yang tertunda
Last-write-wins itu sederhana, tapi punya kasus pinggiran. Untuk proyek ini, petugas lapangan bekerja di wilayah geografis yang berbeda-beda dengan sangat sedikit data yang beririsan, sehingga konflik sungguhan cukup jarang dan LWW masih bisa diterima.
Yang Kami Pelajari
Uji dengan perangkat nyata di kondisi nyata. Emulator tidak mensimulasikan tekanan memori, manajemen baterai, atau perilaku perpindahan jaringan perangkat Android sungguhan di lapangan. Beberapa bug sinkronisasi baru ketahuan saat pengujian di lokasi.
UI sinkronisasi sama pentingnya dengan logikanya. Pengguna perlu tahu apakah yang mereka lihat data terbaru atau data cache. Kami menambahkan indikator "terakhir disinkronkan" yang halus dan satu tombol sinkronisasi manual — itu saja sudah menurunkan pertanyaan ke tim dukungan secara signifikan.
Jaga skema lokal tetap stabil. Setiap kali Anda mengubah skema SQLite lokal, Anda butuh migrasi untuk setiap perangkat yang ada di lapangan. Setelah rilis pertama, kami sangat konservatif soal perubahan skema.
Hasilnya
Petugas lapangan bisa menyelesaikan pekerjaan mereka — mendaftarkan pemohon, memeriksa unit, mengirim laporan — sepenuhnya dalam kondisi offline. Data tersinkronisasi otomatis begitu mereka terhubung ke WiFi. Waktu pemrosesan pengajuan perumahan turun signifikan, dan pekerjaan kertas manual yang selama ini mendefinisikan prosesnya hilang sama sekali.
Kalau Anda sedang membangun sesuatu yang tidak bisa mengandalkan koneksi, kami senang mendiskusikan arsitekturnya. Hubungi kami.