Local-first sync, conflict handling and why your CLI should work on a plane. Practical notes on designing developer tools that do not depend on a connection.

Developers work in all sorts of places. Trains, cafes, conference halls and countries with patchy internet are all normal. A tool that freezes when the network drops feels fragile, and people stop trusting it.

Offline-first is a design approach where the tool works fully on local data and treats the network as a bonus, not a requirement.

The core idea

The app reads and writes to a local store on the device. A background process syncs changes with the server when a connection is available. The user never waits for the network to do their work.

The interface only talks to the local store. Syncing happens behind the scenes.

A sync queue in practice

Every change is saved locally first and added to a queue. When the connection returns, the queue is sent in order. If a send fails, it stays in the queue and is retried later.

queue.js
const queue = loadQueueFromDisk();

async function save(change) {
  applyLocally(change);        // user sees the result immediately
  queue.push(change);
  persistQueue(queue);         // survives a restart
  trySync();
}

async function trySync() {
  while (queue.length && navigator.onLine) {
    try {
      await sendToServer(queue[0]);
      queue.shift();
      persistQueue(queue);
    } catch {
      break; // keep the change, try again later
    }
  }
}

The hard part: conflicts

Two people edit the same thing while offline. When both sync, the server receives two different versions. You need a rule for what happens.

StrategyHow it worksGood forDownside
Last write winsThe newest change replaces the olderSimple settings and preferencesOne person’s edit can be silently lost
Merge by fieldCombine changes to different fieldsRecords with many independent fieldsSame-field edits still conflict
Ask the userShow both versions and let a person chooseImportant contentInterrupts the user
CRDTsData structures designed to merge automaticallyCollaborative text and listsMore complex to build and reason about

Choose the simplest strategy that is safe for your data. Many tools never need anything beyond last write wins plus a visible history.

Design tips

  • Make offline status visible. A small “working offline” indicator avoids confusion.
  • Never block on the network. Show local results first, and update when fresh data arrives.
  • Handle retries safely. Make sync operations idempotent so a repeated send does not duplicate data.
  • Keep a version or timestamp on every record. It makes conflict detection possible.
  • Test with the network off. Use airplane mode as part of your normal testing.