Engineering
How we built billing that keeps working when the internet drops
A shop can't tell a queue of customers to wait for the Wi-Fi. Here is how ShopyDay keeps making bills offline, and why the server never refuses a bill once it has been handed over.
Eternus team · 28 October 2026
ShopyDay is a web app: the counter opens it in a browser, on a PC, tablet or phone. That is what makes it cheap to set up. It also means that when the shop's internet drops on a Saturday evening, the app has to keep working anyway. A customer holding a shirt does not care about the router.
This post is about how we made billing work without internet, and the one design decision that made the rest fall into place.
The decision: a bill that was handed over is a fact
Most apps treat the server as the judge. The phone asks, the server checks, and the server says yes or no. That breaks down offline. By the time the server sees a bill made offline, the customer has already paid and walked out with the printed bill.
So we turned it around. An uploaded bill is saved exactly as printed. The server never refuses it for breaking a shop rule. Anything unusual is flagged on the bill for the owner to check:
- the price changed while the phone was offline
- the discount was above the staff limit, or the item was sold below its lowest price
- the phone's clock was wrong
- the bill belongs to last month, so it needs to go into last month's GST return
The owner sees a short list of bills to look at instead of a cashier fighting an error message. The only bills the server turns away are ones it can't save at all, such as an item that has since been deleted or a bill from a phone that isn't this shop's.
Four pieces that make it work
1. The billing page lives on the phone. A service worker keeps a copy of the offline billing page and the files it needs. With internet, every page loads normally. When a page can't load at all, the browser shows the saved billing page instead.
2. The phone keeps the product list. Products, prices, GST rules and offers are stored in the browser's own database (IndexedDB) and refreshed whenever the phone is online. Billing offline uses this copy, so the GST rates are worked out exactly as they are online.
3. Each phone has its own bill numbers. Two phones billing offline can't ask the server for the
next number. So each phone gets a letter when it is set up: phone A makes SHOP-A00001,
SHOP-A00002 and so on, and phone B makes SHOP-B00001. Numbers never clash, and each series still
runs in order with no gaps, which is what GST asks of bill numbers. Taking the next number and saving the bill happen in one
database transaction on the phone, so a bill number can't be used twice, even if the app is closed
mid-bill.
4. Uploads are safe to repeat. When the internet comes back, waiting bills upload in small batches. Each bill carries its own ID, and the server saves a bill only once: sending it again just returns the copy already saved. A bill leaves the phone only after the server confirms it is saved. If the upload fails halfway, nothing is lost and nothing is doubled.
What we'd tell anyone building offline features
- Decide what is true. For us, the printed bill is the truth and the server records it. Once that was settled, most of the hard questions answered themselves.
- Flag, don't block. Rules still matter, but offline they become things to check later, not walls.
- Make every write safe to repeat. Networks fail at the worst moment. If sending something twice is harmless, retrying is easy.
- Test with the cable pulled out. Airplane mode in the middle of a bill, a closed tab, a phone with the wrong date. Most bugs are found at those edges.
If your business has a workflow that can't stop when the internet does, we'd be glad to talk about it.
Want something like this built for your business?
We build web and mobile software for businesses, and keep it running after launch.