On This Page
1Overview2Offline Architecture Components
3Reliability Design Patterns4Anti-Patterns to Avoid
5References

Overview

The offline-first philosophy inverts the default assumption: instead of designing for network availability and handling offline as an exception, design for offline operation and treat network connectivity as an enhancement. The local database is the single source of truth. The UI reads from the local database exclusively. Network access writes to the local database, which propagates to the UI through reactive observation.

Offline Architecture Components

Local Database as Single Source of Truth

Room (Android) or SwiftData/Core Data (iOS) serves as the authoritative data store. Every network response is written to the local database before the UI sees it. The UI never reads from a network response directly — it observes the local database through reactive queries. This pattern ensures: the UI is always consistent with the local database, network failures produce no UI regression (cached data remains visible), and resuming from the background shows instant content while a refresh occurs in the background.

Repository Cache Strategy

The Repository decides which cache strategy applies to each data type:
- Cache-first (stale-while-revalidate): Return cached data immediately, fetch network update in background. Best for reference data (product catalogues, configuration, user profiles). User sees content instantly.
- Network-first with cache fallback: Try network first, fall back to cache only on failure. Best for user-generated content (transactions, orders) where freshness matters.
- Cache-only: Return cached data, never fetch. For computed data that is expensive to regenerate but changes infrequently.

Delta Sync Protocol

All collection endpoints support a since query parameter accepting an ISO 8601 timestamp or opaque cursor. The mobile Repository stores the watermark of the last successful sync. Subsequent sync requests fetch only records modified after the watermark. Deleted records appear as tombstones (id + deletedAt) for a minimum of 30 days — the Repository removes them from the local database and the UI.

Conflict Resolution

When optimistic updates are used (write to local database immediately on user action, sync to server in background), network rejection requires rollback. Conflict resolution strategies: last-write-wins with server timestamp for simple scalar values; merge strategy comparing field-level changes for structured objects; user-resolution modal for collaborative data where both changes have business value.

Background Sync

Android: WorkManager guarantees execution of sync tasks even after process death and device restart. Constraints: network available, battery not critical. Exponential backoff on failure. iOS: BGProcessingTask for longer sync operations (up to 30 minutes when plugged in); BGAppRefreshTask for lightweight updates (up to 30 seconds). Both honour system scheduling — do not use UIBackgroundModes: fetch as it is deprecated in favour of BGTaskScheduler.

Reliability Design Patterns

Circuit Breaker

Prevent retry storms against an unavailable backend. After N consecutive failures, the circuit opens and fast-fails all subsequent requests for a configurable period. The circuit enters half-open state after the timeout, sending one probe request. If the probe succeeds, the circuit closes. Implemented in the Repository layer using a state machine backed by in-memory state or Object Store v2.

Retry with Exponential Backoff and Jitter

Transient errors (connection timeout, HTTP 503) are retried. Permanent errors (HTTP 400, 401, 404) are not retried — they are error states requiring user action. Retry formula: delay = min(base * 2^attempt + random(0, base), maxDelay). Base: 1 second. Max: 60 seconds. Jitter prevents thundering herd: multiple client instances failing simultaneously recover at different times rather than synchronised retry storms.

Anti-Patterns to Avoid

⚠ 1. Network Calls Blocking the UI Thread

runBlocking { api.getAccount() } on the main thread. Produces ANR (Application Not Responding) on Android, hangs the UI on iOS. Detected by StrictMode in development.

Hover to see the fix ↻
↺ Correct Approach

All network operations on Dispatchers.IO (Android) or a background Task (iOS). UI thread is reserved exclusively for rendering.

⚠ 2. No Offline State

App shows a blank error screen when network is unavailable instead of cached content with a staleness indicator.

Hover to see the fix ↻
↺ Correct Approach

All screens implement the offline-first pattern. Stale data is shown with a timestamp of last successful sync. A reconnection banner appears when network returns and a sync is in progress.

Flowchart

%%{init:{'theme':'base','themeVariables':{'fontSize':'14px','fontFamily':'IBM Plex Sans, system-ui, sans-serif','primaryColor':'#DBEAFE','primaryTextColor':'#1e3a5f','primaryBorderColor':'#2563EB','lineColor':'#374151','clusterBkg':'#F9FAFB','clusterBorder':'#D1D5DB','edgeLabelBackground':'#FFFFFF'},'flowchart':{'curve':'orthogonal','padding':30,'nodeSpacing':65,'rankSpacing':75,'useMaxWidth':true}}}%% flowchart TD UI["🖥 UI Layer Always reads from Local DB"] -->|"Observe via Flow/Combine"| LDB subgraph App["📱 Mobile Application"] LDB["📀 Local Database Room / SwiftData Single Source of Truth"] REPO["Repository Cache Strategy Decision cache-first · network-first"] WM["WorkManager BGTaskScheduler Background Sync"] end subgraph Network["🌐 Network Layer"] BFF["Mobile BFF Delta Sync: ?since=timestamp Tombstones for deletes"] CB["Circuit Breaker Open → Fast-fail Half-open → Probe"] RETRY["Retry + Backoff Exponential + Jitter Transient errors only"] end REPO -->|"Cache miss Background refresh"| CB CB --> RETRY --> BFF BFF -->|"Write response"| LDB WM -->|"Guaranteed execution"| REPO style App fill:#E3F2FD,stroke:#1565C0 style Network fill:#FFF3E0,stroke:#E65100

References

  1. Hood, Chet and Strazzullo, Luciano — Offline-First Apps with Android. Google I/O 2022.
  2. Google — WorkManager Documentation. developer.android.com/topic/libraries/architecture/workmanager
  3. Apple — Background Tasks Framework. developer.apple.com/documentation/backgroundtasks
  4. Nygard, Michael — Release It! Design and Deploy Production-Ready Software. 2nd Ed. Pragmatic Bookshelf, 2018.
Mobile Engineering Reference
← Mobile Development