Skip to content
All articles
Engineering4 min read

Building an app that assumes the power will go out

Offline-first is an architecture decision, not a feature toggle. What it changed about how we store attempts, cache audio and sync streaks.

EEngineering teamMobile and platform · 8 July 2026 · updated 28 August 2026

Most apps treat offline as an error state. A request fails, a spinner hangs, an alert appears, and the user is told to check their connection, as though that were news to them. Building for Nepal makes that posture untenable within about a week of real usage.

Load-shedding, patchy coverage outside the valley and metered data are not edge cases here. They are the median conditions. So offline stopped being a feature we would add and became an assumption we designed against.

What happens when a candidate answers a question

  1. 1

    Tap

    The candidate selects an option.

  2. 2

    Local write

    The answer is committed to on-device storage before anything is sent anywhere.

  3. 3

    Sync

    When there is a connection, the attempt is uploaded. If there is not, it waits without blocking anything.

  4. 4

    Reconcile

    The server score arrives and replaces the provisional local view.

The answer is written to on-device storage first. The user interface updates from that local write. A synchronisation step later sends the attempt to the server, which scores it authoritatively and returns the result to be reconciled locally.

The write path. The network call sits after the local write, which is the entire architectural claim in one diagram.

What that actually changed

Attempts are local first

When a candidate answers a question, that answer is written to on-device storage before anything is sent anywhere. The network call is a synchronisation step, not the write itself. If the app is killed mid-exam, nothing is lost, because nothing depended on the request succeeding.

This is straightforward until you consider scoring. We score on the server, deliberately, because a score computed on the handset is a score a motivated user can change. So the local record is the attempt, and the authoritative result arrives when the sync completes. The app shows a provisional view and reconciles it, and the reconciliation has to be right.

Content is cached deliberately, not opportunistically

A cache that fills up with whatever the user happened to open is not much use when the power goes out. Downloads are explicit: the candidate chooses a lesson set, a vocabulary deck or a listening pack, and it is stored until they remove it. Predictability matters more than cleverness when someone is relying on it.

Audio is the expensive part

Text questions are tiny. A forty-question practice set is well under a megabyte, which is nothing. Listening audio is orders of magnitude larger, and on a metered connection that is a real cost to a real person.

  • Listening packs download once, over Wi-Fi by default, and play offline afterwards.
  • Low data mode drops the streaming bitrate and defers images until requested.
  • Nothing prefetches audio in the background. Ever. Spending someone's data without asking is not a trade-off, it is a bug.

Streaks had to work offline too

A streak that breaks because the user had no signal would punish someone for their electricity supply. So streaks are computed on-device from local activity, and the server reconciles rather than arbitrates. It is slightly more complex and it is obviously correct.

The part that took longest

Conflict resolution. A candidate signs in on a second handset, both devices hold unsynced attempts, and both are legitimate. Last-write-wins would silently discard someone's work, which for an exam attempt is unacceptable. Attempts are append-only and keyed by attempt identity, so two devices produce two records rather than one overwriting the other.

Offline as an error state

  • Request fails, spinner hangs, alert appears
  • The user is told to check a connection they cannot fix
  • Work in progress is lost on a failed write
  • Last-write-wins silently discards the loser
  • Cheap to build, expensive to live with

Offline as an assumption

  • Local write first, sync second, never blocking
  • The interface never mentions the network unless it matters
  • Killing the app mid-exam loses nothing
  • Append-only records keyed by attempt identity
  • Expensive to build, and impossible to retrofit later

It is not the most interesting engineering on the platform, and it is the reason nobody has ever written to us to say they lost a session.

Frequently asked questions

Why not score on the device and sync the result?
Because a score computed on the handset is a score a motivated user can change. Scoring stays on the server; the device holds the attempt, which is a record of what was answered rather than a claim about how well.
How do you handle two devices with unsynced attempts?
Attempts are append-only and keyed by attempt identity, so both devices produce records and neither overwrites the other. Last-write-wins would discard a real exam attempt, which is not an acceptable outcome.
Can offline-first be added to an existing app later?
It can, but it is a data-layer rewrite rather than a feature. Offline-first is a decision about where the source of truth lives, and moving that decision after launch touches almost everything.
Everything inside the platformOffline study packs, server-scored attempts, streaks that survive a power cut, and the rest of the toolset.

Offline-first is not a library you install. It is a decision about where the source of truth lives, and it is very expensive to retrofit. Make it on day one or accept that you will rewrite the data layer later.

About this article

Written by the mobile and platform at iSmartExams in Kathmandu. Exam formats change, and this article states the pattern as we understand it at the time of writing — always check the current notice for the sitting you are entering. If something here is wrong, tell us. We would rather correct it than leave it standing.

Send a correction
Engineering

Reading about it is the easy part.

Everything in this article describes something you can start doing today. Open the practice bank for this exam and find out where you actually stand.