Building for markets with unreliable connectivity taught me that offline-first isn't optional—it's essential for good UX.
The Challenge
Our delivery app needed to work when drivers were:
- In underground parking lots
- In rural areas with spotty coverage
- In buildings with poor signal
Waiting for network requests simply wasn't acceptable.
Core Principles
1. Local-First Data
Every read operation goes to local storage first:
Future<List<Delivery>> getDeliveries() async {
// Always return local data immediately
final local = await _localStorage.getDeliveries();
// Then sync in background
_syncService.syncDeliveries();
return local;
}2. Optimistic Updates
User actions are applied locally immediately, then synced:
Future<void> completeDelivery(String id) async {
// Update local state immediately
await _localStorage.markComplete(id);
// Queue for sync
await _syncQueue.add(SyncAction.completeDelivery(id));
}3. Conflict Resolution
When the device comes back online, conflicts are resolved with "last write wins" for most cases, with manual resolution for critical data.
Tech Stack
- Hive - Fast local NoSQL storage
- Connectivity Plus - Network state monitoring
- WorkManager - Background sync scheduling
Results
- App works 100% offline for core workflows
- Background sync happens automatically when connected
- Users don't notice network issues
The key insight: design for offline first, online as an enhancement.