Aplikasi Field Service yang digunakan di lapangan tidak selalu memiliki koneksi internet yang stabil. Karena itu, data tidak bisa sepenuhnya bergantung pada API.
Solusinya adalah menggunakan Offline-First Architecture dengan SQLite sebagai local database.
React Native UI
↓
Repository
↓
SQLite
↓
Sync Queue
↓
Sync Engine
↓
GraphQL API
1. SQLite sebagai Local Database

Data pekerjaan disimpan di SQLite:
app.db
installations
sync_queue
Contoh `installations`:
uuid
status
installer_id
transaction_id
updated_at
data_json
UI membaca data dari SQLite, bukan langsung dari API.
UI → Repository → SQLite
Dengan begitu aplikasi tetap bisa menampilkan data ketika offline.
2. Sync Queue

Setiap perubahan yang belum dikirim ke server dimasukkan ke `sync_queue`.
sync_queue
id
action_type
payload_json
created_at
Contoh:
UPDATE_INSTALLATION
UPLOAD_PHOTO
START_INSTALLATION_SLA
Flow:
User Update
↓
SQLite
↓
sync_queue
Data tidak hilang meskipun aplikasi sedang offline atau ditutup.
3. Push dan Pull Sync
Sync dibagi menjadi dua proses:
pushData()
pullData()
Urutannya:
Network kembali
↓
pushData()
↓
Kirim perubahan lokal
↓
pullData()
↓
Ambil data terbaru server
Push dilakukan lebih dahulu agar perubahan lokal dikirim sebelum data server ditarik kembali.
4. Optimistic Local Update
Perubahan langsung disimpan ke SQLite.
User
↓
Update SQLite
↓
UI langsung berubah
↓
Masuk sync_queue
↓
Kirim ke server ketika online
Contohnya:
PENDING
↓
IN_PROGRESS
User tidak perlu menunggu response API untuk melihat perubahan.
5. Sync Engine
Sync Engine membaca queue dan menjalankan mutation GraphQL.
async function sync() {
await pushData();
await pullData();
}
Jika request berhasil:
API Success
↓
hapus queue
Jika gagal:
API Error
↓
queue tetap ada
↓
retry pada sync berikutnya
6. Network Detection
`@react-native-community/netinfo` digunakan untuk mendeteksi perubahan koneksi.
Offline
↓
User tetap bekerja
↓
SQLite + Queue
↓
Online
↓
SyncService.sync()
`NetInfo` hanya menjadi trigger untuk melakukan sync. Status connected tidak menjamin API pasti tersedia.
7. Offline Photo Upload

Foto juga mengikuti konsep yang sama:
Camera
↓
Watermark / Processing
↓
Local File
↓
Sync Queue
↓
Upload ketika online
Queue menyimpan informasi operasi upload sampai file berhasil dikirim.
8. Database Concurrency
Karena SQLite dapat diakses oleh screen dan Sync Engine secara bersamaan, project menggunakan beberapa mekanisme:
initPromise
WAL
busy_timeout
mutex
transaction
Tujuannya mencegah:
database locked
race condition
partial transaction
Migration database juga menggunakan:
PRAGMA user_version;
sehingga struktur database dapat berubah tanpa menghapus data user.
9. Sync State
Zustand digunakan untuk menyimpan state proses synchronization:
isSyncing
syncMessage
syncingIds
queueCounts
UI dapat menampilkan:
Mengupload data...
Menunggu koneksi...
3 data menunggu sinkronisasi
Sinkronisasi selesai
SQLite menyimpan data, sedangkan Zustand mengelola state aplikasi.
10. Tantangan Utama
Offline-first bukan hanya masalah SQLite.
Beberapa masalah yang harus diperhatikan:
Duplicate request
Retry
Idempotency
Database locking
File upload
Network recovery
Data consistency
Conflict resolution
Contohnya, request bisa sebenarnya berhasil di server tetapi response gagal diterima device.
Mobile
↓
Request
↓
Server berhasil
↓
Network putus
↓
Mobile menganggap gagal
↓
Retry
Karena itu operasi sync idealnya menggunakan ID/UUID yang konsisten dan mekanisme idempotency di backend.
Kesimpulan
Architecture yang digunakan:
React Native UI
↓
Repository
↓
SQLite
↙ ↘
installations sync_queue
↓
Sync Engine
↓
GraphQL API
Dengan pola ini, aplikasi dapat:
- bekerja tanpa internet,
- menyimpan perubahan secara lokal,
- melakukan optimistic update,
- melakukan retry,
- mengupload foto ketika online,
- dan melakukan sinkronisasi kembali dengan server.
Offline-First bukan sekadar menyimpan data di SQLite. Intinya adalah menjaga data lokal dan server tetap sinkron ketika koneksi tidak selalu tersedia.


