Skip to content

Working offline

SaleSprint is local-first: a change is written to the device’s own database and returns immediately, whether you are online, offline, or the server is down. A background worker pushes it up afterwards. The till never waits for the network.

That design has one consequence worth understanding before anything else. Because the save does not wait for the server, the server’s answer arrives later. A change the server refuses — a validation error, a plan limit, a permission you no longer hold — does not appear as an error on the screen you were using. It turns up in the sync centre, possibly minutes later, as a failed item waiting for you.

Writing works offline across most of the product:

  • Products and the catalog — products, variants, pricing, categories, units.
  • Contacts, leads and loyalty.
  • Staff records, shifts, timesheets and attendance.
  • Companies and locations.
  • Industry-pack records for every trade — job cards, prescriptions, repair tickets, memberships, pawn loans and the rest.
  • Selling at the till — ringing up a sale, taking payment, posting, cancelling.
  • Most stock operations — counts, transfers, receipts, requests, goods issues, kit assembly, landed costs, reservations, and the whole van-sales cycle.
  • Most finance documents — the headers and their lifecycle transitions.

Some areas still need a connection to write:

Still online-only
Purchasing The whole area — requisitions through to supplier payments.
Sales documents other than the till sale Quotations, returns, layaway, backorders, RMAs, trade-ins, deliveries.
Finance sub-records Line transactions, visits, depreciation entries.
User and location assignments Online by design — an administrator changing who can see what needs the server to resolve scope at the moment of the write.

Saving locally does not mean computing locally. The app deliberately does not reimplement pricing, costing, tax or ledger rules on the device — it stores the exact request it would have sent and replays it unchanged. The server does the authoritative work when the change arrives.

So an offline sale shows the cart totals the screen already displayed, but its document number is blank until it syncs, and its cost and profit figures are placeholders until the server fills them in.

One more consequence: stock is not checked against the server while you are offline, so a sale can take the last unit twice across two tills. This is allowed on purpose — refusing a sale because a device cannot reach the server would be worse than reconciling afterwards. Low-stock warnings are advisory offline.

  1. You save. The record is written to the device database and the screen updates straight away. Records created offline get a temporary local identifier so they have a stable key before the server has seen them.
  2. The change joins a durable queue — the outbox — which survives closing and reopening the app.
  3. A worker drains the queue in order. Once the server accepts a newly created record, its temporary identifier is swapped for the real one, and anything you queued against it in the meantime is repointed to follow. A create-then-post sequence therefore arrives in the right order.

The worker runs on app start, when the device regains connectivity, right after you make a change, when you tap retry — and on its own timer. If work is still queued and the device is online, it re-attempts after 5 seconds, then 15, 30, 60 and 120. The timer resets on progress and stops when the queue empties or the device goes offline, so a server that is reachable but unhealthy recovers without anyone tapping anything.

Failures are sorted into two kinds, and the difference decides whether you need to act.

  • Retryable — no network, a timeout, a server error, an expired session. The change stays queued and is re-attempted on the backoff schedule. Nothing to do.
  • Rejected — the server refused it: validation, permission, a plan limit, a conflict. It is marked failed and skipped from then on, so one bad record cannot block everything behind it.

A rejected change is not discarded. It waits in the sync centre until you deal with it — and that is the only place you will ever be told about it.

The app watches whether the server is actually answering, rather than trusting that a connected device means a working backend. Once a request fails, subsequent reads fail immediately instead of each waiting out a timeout, and the app probes periodically to notice when the server comes back.

In practice a backend outage costs you one slow request, not one slow request per screen. Writes are never blocked by this — they go to the outbox as usual.

Do this before closing up, especially after a stretch offline.

  1. Look at the sync button in the top bar — the circular arrow. No badge means nothing is waiting.
  2. Click it. If it says “All caught up — nothing to sync”, you are done.
  3. Otherwise click View all to open the Sync center.
  4. Read the chip: Synced, Syncing…, Offline or Sync error, and the Last synced line beneath it.
  1. Open the sync button and click View all.
  2. Failed items are listed first, in red, with the server’s own explanation underneath.
  3. Click Retry on one item, or Retry all at the top.
  4. To force everything through, click Sync now — the circular arrow in the toolbar.
  5. If the chip says Offline, nothing will move until you reconnect. Queued changes go nowhere and are safe.
  6. If a retry keeps failing, the red line is telling you what is actually wrong — usually a missing field. Fix the record on its own screen. A failed item is skipped on each run so it never blocks anything else.

An unsynced change exists on one device only: it is not on the server, not on anyone else’s device, and not in any report.