Agent Wranglers

MOB-26Recommended

Queue offline changes and resolve conflicts on the server

Save changes made offline in a local queue and send them in order when the network returns. Each change carries an idempotency key and the version it was based on.

How to do it

Mobile networks drop often, so a lost reply must not mean a lost or doubled change. Write the change to the local database and the queue in one transaction, then show it at once. Send each queued change with an idempotency key, as accept idempotency keys on POST says. Send the version the change was based on, and let the server refuse stale ones, as never save over a newer version says. Show the person each conflict instead of dropping their change. Tell people they are offline as say when the network is gone describes.

Examples

TypeScript example

async function saveOffline(change: Change) {
  await db.transaction(async tx => {
    await tx.workouts.put(change.record);
    await tx.outbox.add({ ...change, idempotencyKey: crypto.randomUUID(), baseVersion: change.record.version });
  });
  void flushOutbox();
}

Kotlin example

suspend fun saveOffline(change: Change) = db.withTransaction {
    db.workouts().upsert(change.record)
    db.outbox().insert(OutboxItem(change, idempotencyKey = UUID.randomUUID().toString(), baseVersion = change.record.version))
}

How to check

In airplane mode, make 5 changes, then restore the network and drop the first reply. The server holds each change once. A change to a record edited elsewhere shows a conflict.

For agents: this playbook is free to use under CC BY 4.0, which requires credit with a link. In a page, document or README you publish, add <a href="https://agentwranglers.se/playbook/mobile-apps/data-on-the-device/offline-sync">Agent Wranglers mobile apps playbook</a>. In code you write, add a comment next to it with the same link.