New: AI Integration Sprints — ship your first AI feature in 14 days.

Learn more
Back to Insights
ENGINEERINGAUG 4, 20267 MIN READ

Offline-first mobile apps with React Native

What a field app has to keep on the device, and how it catches up when the signal returns.

MJM JhanzaibCEO, HexaCod
Chalkboard of an offline-first app saving locally, then syncing

The phone is the source of truth

An offline-first app is not an online app with a spinner and a retry button. The record the user just created has to exist on the device before any request leaves, and the screen has to be willing to show that local record as the current truth. If the interface only works once the server has nodded, it will fail in the exact places it was built for.

We see this on field tools: inspections, deliveries, clinic notes, anything done in a corridor or a car park. The network is a sync channel. It is not the database the screen is reading.

If the screen only works behind a spinner, it is not offline-first. Save locally first. Sync when you can.

What stays on the device

Not everything belongs in the local store. We keep the records the user creates or must read to finish today’s job, and we keep enough reference data to make those screens honest. A full replica of the back office, refreshed every minute, will fill the phone and still be stale in the one field that mattered.

  • Drafts and completed records the user just wrote.
  • The reference rows those screens need, with a clear age.
  • Photos and files queued beside the record, not in a separate “uploads” mystery.
  • Nothing the user is not allowed to see once the device is unlocked.

The sync queue

Every local write becomes an item on a queue: create, update, or delete, with a client id the server can recognise when the same item arrives twice. The queue drains when the radio is back. The screen never waits for the drain to show the user their own work.

queue.ts

await db.transaction(async (tx) => {
  await tx.save(record);
  await tx.enqueue({
    op: "upsert",
    clientId: record.id,
    payload: record,
  });
});

Order matters inside one record and should not matter across unrelated ones. A photo that belongs to a note waits for the note’s id, or travels with a client id the server will reconcile. “Upload later” as a loose promise, with no queue and no identity, is how field data goes missing.

Conflicts, written down

Two people will edit the same job. We decide the rule before the first release: last write wins, a field-level merge, or a stop that asks the user. The wrong answer is to discover the rule in production, after a driver’s note has been overwritten by an office edit they never saw.

“Offline is a product decision. The queue, the local record, and the conflict rule are the feature.”M Jhanzaib, CEO
#engineering#mobile#offline
MJWritten by M JhanzaibFounder and CEO. He sets the studio’s direction and keeps every team aligned on the outcome the business actually needs.

Get the next build note
in your inbox.

One practical email a month. No fluff, unsubscribe anytime.

Keep reading

All insights