Offline is an architecture, not a feature

“Works offline” is often written into a requirements document as a single line, next to other single lines. It is not comparable to them. It is a decision about where the truth lives, and it has consequences in the data model, the sync strategy, the interface and the support process.

Made at the start it is manageable. Retrofitted, it usually means rewriting the data layer.

1. The device holds the truth, temporarily

In a connected application the server is authoritative and the client is a view. In an offline-first application the device holds records that exist nowhere else, sometimes for hours, occasionally for days.

That single change means:

  • Identifiers are generated on the device, not by the server. A record must be referenceable before it has ever been transmitted.
  • Local storage is a database, with migrations, not a cache to be cleared.
  • Every record carries state: created, edited locally, queued, synced, rejected. Users need to see it, and support needs to ask about it.
  • Nothing is destructive. Deletion is a flag until it has synced, because a deletion that fails to transmit is indistinguishable from a record that never existed.

2. Design the conflict rules before you write code

Two people edit the same inspection while both are offline. Whatever happens next is a business rule, not a technical detail, and it must be decided with the operation rather than defaulted by a library.

Useful patterns, in rough order of preference:

Make conflicts impossible. Model records as append-only events where you can — a diary entry, a check, a defect report. Two people adding entries do not conflict. This removes most of the problem and is usually available if the model is designed for it.

Field-level merge. Where records must be editable, merge per field rather than per record. Two people editing different fields of the same asset is not a conflict in any meaningful sense.

Last write wins, with the losing version retained. Acceptable for low-stakes fields, and only if the discarded version is recoverable.

Explicit resolution. Present both versions to a person. Correct for high-stakes records, and it must be rare — an operation that resolves conflicts daily has a modelling problem.

Whatever the rule, never silently discard work. A field worker who loses a completed inspection will never trust the application again, and will tell everyone.

3. Sync is a queue, and queues need management

Sync fails in ways users must be able to understand:

  • Order matters. A defect referencing an asset created offline must sync after it. Dependency ordering is your problem, not the network’s.
  • Partial success is normal. Ten records queued, seven accepted, one rejected by validation, two pending. The interface has to represent that honestly.
  • Rejection needs a route back. A record the server refuses must return to the user with a reason, editable, not silently dropped into a log.
  • Retry with backoff, and never assume connectivity means working — captive portals and depot wi-fi that resolves DNS and nothing else are routine.
  • Large attachments queue separately. Photographs are most of the payload; a 30MB upload should not block a 2KB defect report.

4. Time is unreliable

Device clocks drift and can be changed by the user. In an operation where sequence matters — and in inspection and compliance work it always does — this matters.

Record both device time and server-received time, and be explicit about which one any report uses. For anything with evidential weight, the ordering that counts should not depend on a clock anyone can set.

5. The interface is the hard part

Site and depot software is used standing up, outdoors, wearing gloves, in bright sun or in the dark, by someone who wants to be finished.

What this changes:

  • Large targets, generous spacing. Precision is not available.
  • No hover, no long-press-only actions, no gestures that must be discovered.
  • High contrast that survives daylight. Subtle greys are invisible outdoors.
  • Forms that can be paused. Interruption is the norm; a form that loses state is the most common reason capture stops happening.
  • Structured over free text, because typing outdoors is miserable — but with one free-text field, because structure never covers everything.
  • Photographs as first-class input, compressed on device, attached to the record not to a message.

6. Make capture cheaper than the workaround

Every field operation has a workaround: paper, a photo of a form, a text message to the office. That workaround is the competition, and it is very good — it is fast, it never fails, and everyone already knows it.

The application replaces it only if it is genuinely quicker at the moment of use. If completing a check properly takes longer than writing it on paper, people will use paper and someone will re-key it, and you will have added cost while believing you removed it.

7. What this buys

Done properly, the operational effect is not “the app works on the train”. It is:

  • Nothing is re-keyed. Capture happens once, at the point of work.
  • The record assembles itself. Compliance packs, quality records and site diaries are a view over what was captured rather than a project.
  • The gap closes. The delay between something happening and the system knowing is minutes rather than days, which is where most operational risk lives.

We built ECS Group Command on this basis: site packs, briefings, check sheets, plant inspections and site diaries captured once on a phone, offline where there is no coverage, syncing when signal returns, across nine service areas.

8. Testing it honestly

Offline behaviour is not testable on a desk with wi-fi toggled off. Minimum:

  • Airplane mode for a full shift, with real workflows, then sync.
  • Deliberate conflicts, generated by two devices, with the resolution reviewed by someone from the operation.
  • Bad connectivity, not absent connectivity — high latency and packet loss break more things than a clean disconnection.
  • A full storage device, and a device that runs out of battery mid-form.
  • App killed by the OS while a queue is pending, which is the most common real cause of lost work.

A sequence that works

  1. Model the records as events where you can; decide conflict rules where you cannot.
  2. Build local-first storage with device-generated identifiers and record states.
  3. Build the queue, with ordering, partial success and a route back for rejections.
  4. Design the forms for gloves and daylight.
  5. Test on a real shift, with real interruptions, before anyone commits to a rollout.

Building for people working away from a desk? Get in touch, or read about our travel and transport work.

← Back to Travel & Transport