An onboard till that keeps selling with no network

Cabin crew sell from a trolley, with a queue of passengers and no network. We built an onboard sales system where being offline is the normal case, not the error. The working demo won the contract.

Client
Cyprus Airways · Delivered with ThinkCRM
Sector
Aviation
Kind of work
HardwareMobile

The situation

Cyprus Airways cabin crew sell food, drinks and duty-free from the trolley. The system runs the catalogue, discounts, card and cash payments, receipts, trolley stock and the count at the end of each flight. It runs on handheld payment terminals, with a web back office for stock and reports. We delivered it with ThinkCRM, and it goes live in October 2026.

What made it hard

The till must open, sell, count, close and recover for up to 16 hours with no network. Every sale made in the air must land on the ground exactly once, and no passenger can ever be charged twice.

What we did

  1. Started from proven code: the till extends the point-of-sale engine from ThinkCRM’s gym platform, with new parts built for the cabin.
  2. Designed the offline sync as one append-only ledger. Each sale carries an ID that the device creates, and the server stores each one once, so a sale sent five times is recorded once.
  3. Signed every upload with a key for each device, and made the server answer record by record, so one bad record never rejects a whole batch.
  4. Wrote prices, discounts and money handling as one shared library that the device and the server both use, so the aisle and the ground always agree on what a basket costs.
  5. Kept the card out of the till. Payment runs in the terminal’s own payment app. While a card result is unclear, the till blocks every other payment for that basket, cash included, because treating an unclear result as a decline is how a passenger gets charged twice.
  6. Charged in euros, with prices shown in euros, pounds and dollars from daily ECB rates.
  7. Tested the offline design on paper before building it, and closed every conflict and gap that review found before the first line of sync code.
  8. Backed it with automated tests across the API, the back office and the device.

Before and after

What made it hardWhat we built
No network for up to 16 hoursOffline is the normal path
Retries could duplicate a saleEach sale stored exactly once
Two pricing engines would driftOne shared pricing library
A card result can be unclearAll payment paused until it is clear

What we would do differently

Our first terminal build carried only 64-bit libraries, and the older 32-bit terminals refused it with a misleading error. The fix took minutes. The build check that now fails when the 32-bit part is missing took longer, and mattered more.

Built with

Expo · React Native · NestJS · PostgreSQL · Payment terminals

Ready to build something great?

Tell us what’s breaking, or what you need built. You talk to the engineer who does the work.