Skip to content
AB

Offline-First Android Data with Room and Supabase

Render from local truth, synchronize explicitly, and model freshness and conflicts instead of hiding them.

Ashish BhakhandPublished

If every screen waits for Supabase, the app feels unreliable on mobile networks. If Room is merely an unstructured fallback, local and remote state drift.

Use Room as the observable source for UI:

Code
val workouts: Flow<List<Workout>> = dao.observeWorkouts(userId)

Refresh pulls remote changes into a transaction. Local writes update Room immediately and enter a pending-sync state. A worker later pushes them and records acknowledgement.

Each record needs stable identity and enough metadata for conflict handling. Deletions require tombstones until remote acknowledgement or another device may restore them.

Separate freshness from content. Existing local records plus a failed refresh is different from an empty account. Expose last successful sync and pending writes where the product benefits.

Authentication changes require partitioning or clearing user-owned local data. Never show the previous account's cache while a new session initializes.

Supabase can expose database-shaped APIs, but mobile features should still use repositories and domain mappings. That boundary protects UI from schema details and makes offline policy testable.

Test process death after local write, duplicate pulls, delayed acknowledgements, logout, and two devices editing the same record. Offline-first is a consistency model, not a cache flag.

← Back to all writing