When the Signal Dies: Engineering Offline-First Mobile Architecture for Africa's Real Conditions

An engineering guide to building software for unreliable power, intermittent connectivity, and constrained devices.
I. The Woman Who Kept Working When the Bars Disappeared
Imagine a nurse in a rural clinic outside Kabwe, a market trader in Kariakoo, or a loan officer between Kisumu and the Ugandan border. A connection can disappear because of local power or network faults, congestion, or a wider infrastructure outage. The work does not necessarily stop when the signal does: the patient is still waiting, the customer still wants the sale recorded, and the client still needs the loan disbursed.
For some users and workflows, this is a routine condition rather than an edge case.
Some software assumes reliable power and connectivity, treating a dropped connection as an exception. For workflows deployed where coverage or power is intermittent, the application should continue useful work while disconnected and use a live connection when available. That change in assumptions is central to offline-first design.
What follows is an engineering guide: it describes selected infrastructure and device constraints, with sources for the figures retained below, and outlines ways a team can design for them.
II. The Ground Truth: What “African Operational Realities” Actually Means in 2026
It is worth being precise here, because vague gestures toward “unreliable infrastructure” do a disservice to both the problem and the people living inside it. The picture is uneven, improving in places, worsening in others, and rarely what the headlines from five years ago suggest.
The Grid
South Africa's power conditions have changed over time, and the end of scheduled load-shedding does not mean every household or business has reliable electricity. Local faults and outages can still interrupt power. For software, the important distinction is between planned interruptions and unpredictable local ones: the latter cannot reliably be scheduled around.
Grid reliability also varies by location. Claims about outage counts depend on the area, the time period, and how outages were measured; without a representative national source, a single provider's monitoring data should not be presented as a national household average.
Across Sub-Saharan Africa, access to electricity remains uneven across and within countries. World Bank data are reported by country and year; access figures should not be confused with the reliability or quality of supply. For product teams, the practical point is that reliable grid power cannot be assumed for every user or location.
The honest conclusion is not “Africa has no power.” It is: power reliability varies enormously by country and even by neighbourhood, unplanned outages are common even where planned ones have stopped, and hundreds of millions of people still have no grid connection whatsoever, relying instead on solar home systems, generators, or nothing. Any architecture that assumes a phone will always have charge, or that a shutdown will always be a clean one, is designing for a market that does not exist.

The Cable at the Bottom of the Sea
Submarine cables are part of the physical infrastructure that carries international traffic. If a route fails, the effect depends on available alternatives and the particular services a user relies on. An app should not assume that a working mobile signal guarantees an available route to every service.
A cable fault or other network interruption can affect service until traffic is rerouted or infrastructure is repaired. Applications should handle loss of connectivity gracefully rather than assume that a working mobile signal guarantees an available route to every service.
The pattern is structural, not a one-off. The number and causes of cable faults vary by year and route. Network redundancy can reduce the effects of individual failures, but it does not eliminate the possibility of regional disruption.
The Handset in the Pocket
GSMA reports that mobile technologies and services contributed $240 billion to Africa's economy in 2025, equivalent to 7.8% of GDP. GSMA also reports that nearly one billion people—63% of the population—were not using mobile internet despite mobile broadband coverage, citing affordability, device access, digital skills, and relevant content among the barriers. Coverage therefore does not mean that every person can or does use mobile internet.
GSMA identifies affordability and device access as barriers to mobile internet use. Device capabilities and prices vary substantially across markets, so teams should validate their target users' devices instead of assuming a uniform handset or memory profile.
Many users rely on lower-cost mobile devices, but device specifications vary by market and model. This is an engineering constraint worth measuring directly: an app that assumes ample memory, unrestricted background activity, and continuous connectivity may perform poorly on the devices its users actually have.
Mobile network generations and shutdown timelines also vary by country and operator. Legacy networks may remain available alongside newer generations during transitions, so app teams should test real devices and network conditions relevant to their users rather than infer support from a regional average.
The Bill
Mobile data affordability varies considerably by country, provider, plan, and measurement method. GSMA identifies affordability as one of the barriers to mobile internet use. Teams should avoid treating a continent-wide average—or an isolated price comparison—as representative of each user's data costs.
What this means in practice is that data usage is not a neutral technical parameter for most African users — it is a recurring, meaningful financial decision, made under real budget pressure, every single time an app pulls data over the network. An engineering team that treats a 40MB app update or an uncompressed full-resolution image sync as a trivial background event is, functionally, asking users to make a choice between the app and something else they need to buy that week.
III. The Principle: Offline Is the Baseline, Not the Exception
For an application that must remain useful offline, the local device can act as the primary data store rather than a disposable cache. The network then becomes a channel for reconciling changes, not a prerequisite for every interaction. Reads can use locally available data; writes should be saved locally when validation and storage succeed, with synchronization attempted later when a connection is available.
This is sometimes called “local-first” software. Martin Kleppmann and colleagues' 2019 essay “Local-First Software: You Own Your Data, in Spite of the Cloud” helped articulate the approach, and a range of tools now support it. Teams working in environments with extended offline periods, costly data, lower-memory devices, or abrupt power loss should test those constraints directly rather than assume that a design for reliable connectivity will suffice.
IV. The Architecture, Layer by Layer
1. The Local Store as Source of Truth
On React Native, teams may use SQLite directly or a layer such as WatermelonDB, which builds reactive queries on SQLite. Flutter options include Hive, Isar, and drift; browser-based applications may use IndexedDB through a wrapper such as Dexie.js or an embedded database such as PGlite. These tools have different trade-offs and resource requirements, so measure them on representative devices and workloads.
One caution belongs here: MongoDB discontinued Atlas Device Sync on 30 September 2025. That date concerns the managed sync service; it should not be conflated with the status or maintenance of every Realm client database or community fork. Teams evaluating Realm should check MongoDB's current deprecation notice and migration guidance rather than assume that an old tutorial still describes a supported sync service.
2. The Outbox: Capturing Intent Before Connectivity
Every write a user makes — a form submitted, a sale recorded, a status updated — should be captured as a discrete, timestamped mutation and appended to a local queue (commonly called an “outbox” or mutation queue), independent of whether a network exists at that moment. The UI reflects the change immediately (optimistic update), and a background process is responsible for draining the queue against the server whenever connectivity is confirmed.

This pattern — sometimes summarised as “the local store is not a cache, it is the primary store” — is the single most load-bearing idea in the whole discipline. It is also, by most accounts from teams that have shipped this in production, a simpler problem than it first appears for the majority of apps: most offline-first products do not need real-time collaborative editing, they need reliably queued writes that eventually reach the server. That distinction matters for the next decision.
3. The Sync Engine and Conflict Resolution
A sync engine pushes queued local mutations to a server and pulls remote changes, with a conflict policy for cases where the same record changed in two places. Product capabilities and supported backends change, so check the current vendor documentation when comparing options. Examples with different models include:
- PowerSync — synchronizes selected data from supported backend databases to client-side SQLite; its architecture separates the sync service from the application's backend write integration. Check its current documentation for supported source databases and configuration.
- Electric (formerly ElectricSQL) — a Postgres-focused sync engine that can be paired with client-side tools such as TanStack DB. Check current documentation for its supported platforms and persistence integrations.
- Ditto — supports device-to-device synchronization through mesh networking, which can be useful when nearby devices need to exchange data without reaching a central service. Validate radio range, battery use, and security for the intended deployment.
- Jazz — a local-first framework for applications that need shared, collaborative data.
- Automerge and Yjs — CRDT libraries for applications that need concurrent shared editing. A CRDT can be unnecessary complexity when the requirement is only to queue one user's writes for later synchronization; choose a conflict strategy that fits the product's actual collaboration needs.
A sync product that suits one team may not suit another. Compare the supported backend, client platform, data model, conflict behavior, offline write path, and the amount of synchronization logic your team must maintain before choosing.
Conflict resolution commonly uses one of several strategies. Last-write-wins (LWW), where a timestamp determines which value prevails, is simple but requires care with clock skew and may be unsuitable for high-stakes data. Field-level merging can preserve non-conflicting changes, such as a name update and a phone-number update to the same record. CRDTs can be designed to converge under concurrent edits without a central coordinator, but may be unnecessary for an app that only needs to queue one user's writes for later synchronization.
4. The Tombstone Problem
Here is a failure mode specific enough to be worth naming precisely, because it is the kind of bug that only shows up in the field, weeks after launch, and is genuinely hard to reproduce in a well-connected testing environment: when a record is deleted, the deletion itself must be synchronised, not just the absence of the record. This is typically done by writing a “tombstone” — a marker recording that the record existed and was deleted, along with a timestamp — rather than simply removing the row.
The trap is retention. If the backend purges tombstones while a device is offline, that device may miss a deletion on its next sync and reintroduce a stale record. Set tombstone retention according to the longest offline interval the product is expected to support, and define how old client schemas and unsynchronized outbox entries are handled during migrations.
5. Background Sync Under Real Constraints
Modern mobile operating systems actively work against naive “just sync in the background” assumptions, for good reason — unmanaged background activity is the single biggest drain on battery life, and battery life is precisely the resource under greatest pressure in a region where mains power itself is unreliable. On Android, background work scheduled through WorkManager is subject to Doze mode and App Standby buckets, which can delay or batch execution significantly, especially for apps the OS has learned the user opens infrequently. On iOS, BGTaskScheduler offers execution windows the operating system grants at its own discretion, not the developer's. A serious offline-first architecture works with these constraints rather than fighting them: batching sync operations, using exponential backoff with randomised jitter on retries (so that when a downed cable is finally repaired and thousands of devices in the same region regain connectivity simultaneously, they don't all hammer the server in the same instant), and reserving foreground-service-level priority only for genuinely time-critical syncs rather than routine housekeeping.
A second, less discussed reliability trap is trusting the operating system's own connectivity flag. “Connected to Wi-Fi” is not the same as “has a path to the internet.” Captive portals on shared or public Wi-Fi, data bundles that silently exhaust mid-session, and carrier-level throttling all produce a device that reports itself online while every real request times out. Robust sync engines perform an actual lightweight network probe — a small request to a known endpoint — rather than trusting the OS-reported state, and treat “connected but unreachable” as its own distinct condition with its own retry behaviour.
6. Bandwidth as a Moral Constraint, Not Just a Technical One
Because mobile data affordability varies substantially by market and user, payload efficiency is more than a performance nicety. Practical steps include syncing only the data relevant to a user or role, sending deltas where appropriate, choosing compact formats when their added complexity is justified, compressing images, and paginating historical data instead of requiring a new install to download an entire multi-year history before it becomes usable.
7. Surviving the Power Cut Mid-Write
If power fails during a write, storage must preserve data integrity. SQLite documents atomic transactions, including recovery from operating-system crashes or power failures; durability also depends on configuration and the underlying storage behaving correctly. This is one reason to prefer a mature, documented database over an ad hoc file format, while still testing the exact device and settings used in production.
8. Designing the Interface for Trust
None of the backend discipline matters if the interface lies to the user about what state they're in. Good offline-first UX makes the sync state legible rather than hidden: a clear, honest indicator of whether a given piece of data has been saved locally only or confirmed on the server; queued actions that are visibly present rather than silently vanished; and, when a genuine conflict does occur and can't be silently auto-merged, a surface that shows the user both versions rather than picking one arbitrarily and discarding the other. Trust, in a system that is deliberately built to work while disconnected, has to be earned through honesty about what “saved” actually means at any given moment — not through pretending the network was never a variable at all.
V. Two Proofs From the Field
USSD: Mobile Services Without Mobile Data
USSD provides interactive services over a mobile network without requiring mobile data. It still depends on the mobile network and service being available, so it is not the same as an application continuing to operate offline. This distinction helps teams decide whether a workflow needs USSD, local storage, or both.
Offline Form Collection: ODK Collect and KoboToolbox
ODK Collect and KoboToolbox are examples of field-data tools that support offline form completion and later submission when a connection is available. They are separate projects, so their supported workflows and limits should be checked in their respective documentation. They demonstrate the practical value of storing submissions locally instead of making connectivity a prerequisite for data entry.
VI. Choosing a Stack in 2026: A Practical Decision Frame
There is no single correct answer. These examples are a starting point for evaluating options, not a universal ranking:
- Building on React Native, want maximum control, willing to build your own sync server: SQLite directly, or WatermelonDB for its reactive layer over SQLite.
- Building on Flutter: consider drift, Hive, or Isar for local persistence, then compare their APIs and performance on representative devices.
- Considering managed sync for an existing backend: check PowerSync's current documentation for supported source databases, platforms, and pricing.
- Considering a Postgres-focused sync engine: evaluate Electric alongside its current client and persistence integrations.
- Need nearby devices to sync without an internet route: evaluate Ditto's peer-to-peer capabilities against the deployment's connectivity, security, and battery requirements.
- Need genuine real-time collaborative editing of shared documents by multiple concurrent users: evaluate Jazz, Automerge, or Yjs against the required platforms and data model.
- Evaluating Realm or Atlas Device Sync based on an older tutorial: check MongoDB's current deprecation notice and migration guidance, since Atlas Device Sync was discontinued on 30 September 2025.
Beneath any of these choices, the constant discipline is the same: local data is the primary store, every write is captured whether or not a network exists, sync is a background reconciliation process rather than a blocking dependency, tombstones outlive your longest realistic offline window, payloads are as small as the data will honestly allow, and the interface never pretends the network is more reliable than it actually is.
VII. Closing
There is an old discipline, in places where the rains do not always come on schedule and the river does not always rise when the calendar says it should, of building the granary a little larger than this year seems to need, of keeping the second well dug even when the first one is flowing well. It is not pessimism. It is a form of respect for conditions as they actually are, rather than as a brochure describes them.
Software is no different. An application that assumes the network will hold, the battery will charge, the cable under the ocean will stay intact, is an application built for a country that does not exist — not South Africa in its best year, not Kenya on its best network, not anywhere. The nurse outside Kabwe does not need an app that apologises when the signal drops. She needs one that was built, from its very first architectural decision, to already know the signal would drop, and to keep working anyway — quietly, faithfully, the way she does.
That is not a lesser standard of engineering. It is, if anything, the harder and more honest one.
Sources
- GSMA, The Mobile Economy Africa — 2025 economic contribution and mobile-internet usage gap
- World Bank, Access to electricity (% of population) — country-level data and survey years
- MongoDB, Atlas Device SDKs deprecation — service status and migration guidance
- Ink & Switch, Local-First Software: You Own Your Data, in Spite of the Cloud — local-first principles
- PowerSync documentation — supported databases and sync architecture
- Electric documentation — Postgres sync engine
- Ditto and Jazz — vendor information on mesh and local-first application models
- Automerge and Yjs — CRDT and collaboration libraries
- Android Developers, WorkManager — persistent background work
- Apple Developer Documentation, Background Tasks — iOS background execution
- SQLite, Atomic Commit and Write-Ahead Logging — transaction and durability behavior
- ODK Collect documentation — offline form workflows
- KoboToolbox Help Center — form and submission workflows
The retained regional figures are attributed to GSMA and should be read in the definitions and time period used in that source. Electricity-access statistics are time-series estimates, not real-time measures of power reliability.