Offline Mode
Hyvä POS is in closed beta
Hyvä POS is currently in a closed beta (pilot phase) with a small group of merchants. It is not yet generally available: the App Store release follows the pilot, and features and configuration may still change - possibly in backwards-incompatible ways - before the general release. Want to take part? Sign up at hyva.io/pos.
The store Wi-Fi dies, the fibre gets cut, or Magento is in maintenance mode for a deploy. With PRO, the register keeps selling.
Two design choices make this possible, both explained in the how-it-works section: the register prices carts on the device and places finished orders in one call (how orders are placed), and the register record is a local receipt written before any network is involved. This page covers what that buys you when the connection is gone.
What Works Offline
- The catalog: PRO keeps an offline product cache on the device (configurable refresh interval), so browsing, scanning and pricing keep working.
- Sales: every sale is stored as a local receipt on the device, exactly as when online.
- Payments: cash always works. Card payments keep working when your terminal has its own connectivity (Mollie terminals take a SIM card as network backup), because payment goes from terminal to provider, not through Magento.
- Staff login: PINs verify against securely cached credentials after the first online login.
Orders queue on the device and sync when the connection returns. Nothing is lost, and nothing needs to be re-entered.
How the Sync Works
Every offline sale sits in a queue on the device, oldest first. Three things drain it:
- Reconnect, immediately. The register watches connectivity. The moment the network returns, it waits a short random delay (one to eight seconds, more on why below) and starts syncing.
- A safety-net poll. Even without a detected reconnect event, a register holding queued sales retries on a schedule: every 30 seconds when things are healthy, backing off after failures (below).
- Manual retry. Any queued sale can be pushed by hand from its detail view.
Sales sync one at a time, in order. On PRO, each sale syncs receipt first, order second: the immutable receipt record (and its QR token) must exist in Magento before the order that references it, so the fiscal trail is never behind the commercial one. See receipt sync.
Two kinds of failure are treated differently, on purpose:
- Network problems (timeout, unreachable, connection lost mid-sync) keep the sale queued and retry automatically. These resolve themselves.
- Business errors (Magento rejects the order for a real reason) stop retrying and land in Reports → Sync Issues for a person to look at. Retrying a genuinely broken order forever would just generate noise.
What Is Cached, and How Fresh It Is
The offline cache holds the product catalog (including prices, tier prices and the attributes promotion rules match on), the category tree, the customer list and the recent orders. It refreshes on a configurable interval, and incrementally: after the first full sync, only records changed since the last sync are fetched (with a safety overlap), in gentle batches.
Honest boundaries: customer-specific (B2B) prices, gift-card balance checks, pay-by-invoice credit checks and live stock levels need the connection; cached quantities are as fresh as the last sync. The header shows how old the cached data is whenever the register is serving from cache.
Built for the Worst Case, Not the Demo
Imagine a retail chain: 50 stores, two registers each, and Magento is unreachable for half an hour. When it comes back, a hundred registers are holding queued orders. If they all pushed at once, they would knock the store right back over. So they deliberately do not:
- Jitter. Each register waits a random one to eight seconds after reconnecting before it starts, so the fleet does not synchronise into one wave hitting Magento in the same second.
- Queue-aware throttling. Between orders, a register pauses: half a second on a small queue, growing with queue depth up to three seconds per order. The bigger the backlog, the gentler the drain.
- Exponential back-off. If a sync round fails, the retry schedule doubles: 30 seconds, then one minute, two, four, capped at five minutes. A register never hammers a server that is already having a hard time, and the back-off resets the moment a round succeeds.
Duplicates cannot happen at any point: every sale carries a unique id (pos_sale_id), so a retry whose earlier attempt did reach Magento gets the existing order back instead of creating a second one, even if the confirmation was lost on the way.
Where the Data Lives
- On the device: queued sales are simply local receipts whose order has not reached Magento yet - encrypted files, stored per configured store, immutable. The offline catalog cache is likewise a set of encrypted per-store files, so two configured stores never mix data.
- In Magento, after sync: a normal order. Its
created_atis the moment it reached Magento (preserving the order-number chronology accounting systems rely on); the moment it happened at the register is stored separately in thepos_sale_atcolumn on the order, available as a sortable "POS Sale Date" column in the admin order grid (hidden by default - enable it via the grid's column picker). The receipt the customer got, with the register timestamp, is mirrored by receipt sync.
Configuration
Offline selling is part of the PRO license; the order queue syncs against the PRO order endpoint, so a terminal needs an active license for the queue to drain.
The device-side knobs live under Settings → Data & Sync on the register:
- Sync interval for the offline catalog: from 1 minute to 1 hour (default 5 minutes). Busy catalogs want short intervals; huge catalogs on weak servers want longer ones.
- Fast product lookup: keeps products cached in memory so a barcode scan hits the cache first and the API only as fallback - this is also what makes scanning instant when online.
There is nothing to configure in Magento for offline mode itself; the queue, retries and back-off are built in.
What to Expect in the App
The header shows a Not connected pill with the reason and a reconnect action, plus a badge counting queued sales. Queued sales are visible with their sync state, any sale can be retried by hand from its detail view, and sync issues (if any) are listed under Reports → Sync Issues with the cause, so nothing fails silently.