Designing a mobile app for an unstable connection
The product decisions — not just the technical ones — that keep VALIDE usable when the network drops.
When you build for the Cameroonian market, an unstable connection is not an edge case. It’s the average case. The question isn’t “how do we handle offline” — it’s “how do we design an experience that stays useful when the network is unreliable.”
What “unstable connection” really means
Three different patterns, each handled differently:
- No network at all — the user is somewhere without coverage. They know. They expect an honest experience.
- Slow network — 2G or EDGE. 800 ms ping, throughput under 20 KB/s. The user may not know it’s slow; they think the app is broken.
- Network that drops — 4G that loses the carrier for 20 seconds, then comes back. The worst case for an architecture that assumes a stable HTTP session.
The product decisions that mattered
Assume the first screen opens offline. VALIDE’s home screen shows already-consulted resources before any network call. We load the local cache first, then refresh in the background. Result: perceived open time divided by three on a slow network.
Make network status visible without being anxiety-inducing. A small, discreet indicator top-right, never a red “no internet” banner. The message: “we’re continuing with what you have, we’ll retry later.” The user doesn’t have to act.
Prioritise optimistic writes. Posting a forum reply or bookmarking a resource: the action is stored locally immediately, with a visual “pending sync” state. When the network comes back, sync happens in the background. If it fails, we notify discreetly — without losing the content.
The technical choices that supported those decisions
- Native Firestore cache — far more reliable than a home-made cache;
- Write queue with
WriteBatch— atomicity even if the connection drops mid-transaction; - Bounded resource sizes — a 15 MB PDF is 3 minutes of download on 2G. We segmented it by page;
- Smart connectivity detection —
connectivity_plusalone isn’t enough; we double-check with a light ping on a health endpoint.
What I wouldn’t do again
- try to “fake” instant loading by pre-fetching everything — that burns the user’s data, which they pay for;
- show a skeleton screen for more than 800 ms — beyond that, users think it’s broken;
- use a third-party offline library without understanding its conflict strategy — conflicts happen, and resolving them blind costs more than planning for them.
An app that works offline is not an app with a “degraded mode.” It’s an app whose default experience does not depend on the network at every tap.