Offline-First di Flutter: Strategi Sinkronisasi yang Saya Pakai
Cara saya menangani konflik data dan sinkronisasi pada aplikasi Ventri Farm — yang harus tetap berjalan di kandang tanpa sinyal.
Wafik Ulinnuha
Backend Developer
Aplikasi Ventri Farm dipakai di kandang ayam, jauh dari menara seluler. Sinyal hilang setiap beberapa menit. UX yang menunjukkan loader saat kehilangan koneksi sama dengan tidak bisa dipakai. Solusinya adalah desain offline-first.
Prinsip yang saya pegang
- Tulis lokal terlebih dahulu. Setiap aksi user berbentuk record di SQLite, lengkap dengan
local_id,created_at, dan flagsync_status. - Server adalah sumber kebenaran final. Lokal hanya cache yang authoritative sampai sinkron berhasil.
- Konflik diselesaikan deterministik. Tidak ada dialog "pilih versi mana" untuk operator lapangan.
Skema data lokal
Saya pakai drift (sebelumnya Moor) di Flutter. Setiap tabel domain punya tabel bayangan untuk antrian sinkron:
class FieldEntries extends Table {
TextColumn get localId => text()();
TextColumn get serverId => text().nullable()();
IntColumn get version => integer().withDefault(const Constant(0))();
TextColumn get payload => text()(); // JSON
IntColumn get syncStatus => intEnum<SyncStatus>()();
DateTimeColumn get updatedAt => dateTime()();
@override
Set<Column> get primaryKey => {localId};
}
Strategi resolusi konflik
Untuk Ventri, kebanyakan entitas adalah append-only (catatan kejadian). Konflik nyata jarang terjadi. Untuk yang mutable (master data ayam), saya pakai Last-Write-Wins berdasarkan vector clock sederhana: server menyimpan version yang naik setiap update, dan klien wajib mengirim If-Match versi terakhir yang dikenalnya. Server menolak update jika versi sudah lebih baru, dan klien diminta merge ulang.
Background sync
Saya tidak memaksa sync di main isolate. Worker terpisah berjalan setiap 30 detik (saat foreground) atau dipicu oleh workmanager setiap 15 menit (background). Antrian adalah FIFO, tapi saya batch maksimal 50 record per request agar payload tetap waras saat 4G muncul.
Apa yang akan saya lakukan berbeda
- Pakai CRDT (seperti Automerge) sejak awal untuk entitas yang collaborative. Tapi untuk single-operator-per-record, LWW sederhana sudah cukup.
- Lebih agresif dalam metric sinkronisasi: berapa lama record duduk di antrian? Berapa rasio konflik? Tanpa angka ini, sulit memutuskan optimasi.
Offline-first bukan fitur tambahan. Ia mengubah cara kita memikirkan domain model. Investasinya nyata, tapi return-nya juga nyata: aplikasi yang tidak menyalahkan operator karena WiFi-nya hilang.
Bacaan lanjutan
Bacaan lanjutan
Mendesain SaaS Multi-Tenant di PostgreSQL Tanpa Menyesal
Pemilihan strategi multi-tenant menentukan biaya operasional, keamanan, dan kemudahan migrasi sekian tahun ke depan. Inilah panduan jujur dari pengalaman membangun Gatsu.
Astro Islands vs Next.js App Router: Memilih dengan Konteks
Bukan soal mana yang lebih cepat. Soal mana yang sesuai dengan bentuk produk dan kemampuan tim. Berikut pertanyaan yang saya tanyakan sebelum memilih.