How the cashier works without internet
The internet drops and customers do not wait. This article explains what is stored on the device, how invoices are numbered temporarily, how they reach the server in the right order without duplicates, and the few operations that need a connection.
On this page
The idea in two lines
The cashier app does not ask the server at every operation. It keeps a copy of everything it needs on the device, saves every invoice locally first, then sends it to the server when a connection is available. That is why selling, printing, returns and holding orders all work while the internet is down.
What is stored on the device
At sign-in and at every sync the app downloads in one call: the POS settings (sales currency, cash rounding, whether prices include tax), items with their units, barcodes and price tiers, item groups, customers with their balances and limits, price lists, promotions, quick items, print templates and cash accounts. All of this is stored in the device database.
Sync is differential: the app sends the catalog version it holds and the server returns only what changed, so it is fast even on a weak connection. Once a day a full sync runs to pick up what was permanently deleted. In "Settings" you see "Last sync" and a "Sync items" button, and in the top bar a "Sync now" button.
When to press "Sync now"
After the manager changes a price or adds an item or a promotion and you want it immediately. Otherwise there is no need: automatic sync runs every minute, after every sale, and when the app returns to the foreground.
The invoice before it reaches the server
- A temporary local number in a format carrying the device number and a counter, printed on the receipt until the official number arrives from the server. The official number is assigned only when posting on the server, so two devices never collide.
- A unique identifier for every document, generated by the device. It is what prevents duplicates: if an invoice is sent twice because the connection dropped mid-send, the server returns the same result and does not create it again.
- Payments inside the invoice: cash, card and cheque are sent with the invoice itself, so the server creates the receipt voucher and allocates it in the same operation.
Sync order
Pending documents are sent in one batch in a fixed order: shifts first (open and close), then invoices, then returns, then cancellations. This way every invoice finds its shift open, every return its invoice, and every cancellation its document. A rejected item does not stop the batch; it is flagged alone and the rest are accepted. On the server, each cashier's documents are grouped in their own shift, and the device that created them is recorded.
The server recalculates
The server does not trust the device total; it recalculates the invoice with the same specification the app uses (prices, units, discounts, promotions, tax, rounding) from its own catalog. If the two totals differ by more than the rounding tolerance set in settings, the invoice is rejected with a message stating the device total and the server total. This usually happens when the device sells at an old price after the manager changed it; the fix is in Pending and rejected.
What happens in the books
Nothing is recorded in the books at the time of sale if the connection is down; entries, stock moves and the receipt voucher are all created the moment the invoice reaches the server, dated as the document was created on the device. So dashboard figures and reports may lag reality by the length of the outage, and correct themselves as soon as the connection returns. Sales reports are in Financial and VAT reports.
What actually needs internet
| Works offline | Needs a connection |
|---|---|
| Selling by scan and search, discounts, promotions, picking a stored customer | Signing in for the first time on the device and attaching it |
| Payment by every method and printing from stored templates | Defining a new item from the screen |
| Returns, holding orders, cancelling a local invoice | Defining a new customer from the screen |
| Opening and closing the shift (sent with the first batch) | Knowing the official invoice number, and refreshing balances and prices |
| Checking the credit limit locally with the last synced balance | The final verdict on the credit limit at the server |
The shift while offline
A shift can be opened and closed without internet; both are sent with the first batch. A closing cannot land in the batch before its invoices because the order is fixed. If the server refuses the closing (a shift already closed, for example), its message shows on the device instead of a silent close. Also, an opening float computed from the cashbox ledger balance is computed on the server the moment the opening arrives, not the moment you pressed the button, as in Opening the shift.
Several devices in one shop
Each device keeps its own catalog and pending documents. When the internet returns the devices do not all rush the server at the same instant: the app delays retries with increasing back-off and a little randomness. The restaurant app has another path inside the shop over the local network between the main POS and the ordering devices, as in Waiter device and kitchen display.
Frequently asked questions
Are invoices lost if the app is closed before the internet returns?
No. Every invoice is saved in the device database the moment payment is confirmed, and is sent at the first connection even days later. Do not uninstall the app or clear its data before you confirm "All documents are synced".
Why does the printed receipt number differ from the number in the panel?
A receipt printed offline carries the temporary local number. The official number is assigned when the invoice reaches the server and shows in its details on the device and in the panel. Reprinting after sync carries the official number.
How long an outage can the app tolerate?
There is no time limit on what is pending on the device. But everything sold offline is sold at the last synced prices and balances, so the longer the outage the higher the chance an invoice is rejected because of a price change or an exceeded credit limit.