Skip to content

One POS system that keeps every store in sync

A point-of-sale platform that unifies in-store checkout, inventory, and store-level reporting into one dependable system built for the shop floor.

Group ledger

Every sale, refund, transfer and count from all 22 stores, written into one book as it happens

LiveAll storesSat 12 Sep 2026
Stores writing
22 of 22
Tills holding offline
1 14 sales held
Last write
0.4 s ago Kingsmead · Till 3
Stock figures
1 per SKU per location
Nightly file exchange
None

The book, sale by sale

Newest first · written in each register's own sequence
TimeStore · tillEventDetailAmount
16:14:09KingsmeadTill 3 · #6120Sale4 items · card£11.95
16:14:08Saltney RoadTill 1 · #3387Split tender£20.00 card · £5.00 cash · £2.21 back£22.79
16:14:06Dorrick ParkTill 4 · #5902RefundSteel flask 500 ml · against sale 5874−£18.50
16:14:05Wenlow GreenTill 2 · #2764Sale2 items · contactless£5.25
16:14:03WarehouseT-881TransferOat milk 1 L +24 → Kingsmead—
16:14:02Abbots QuayTill 1 · #4015Sale7 items · card£26.40
16:14:00Dorrick ParkTill 2 · #4480Sale5 items · card£17.35
16:13:58KingsmeadTill 1 · #6377Sale1 item · cash£3.40
16:13:57Saltney RoadTill 3 · #1928CountGreek yoghurt 500 g −2 (damaged)—
16:13:55Wenlow GreenTill 1 · #3011Sale3 items · card£9.10
16:13:54Abbots QuayTill 3 · #2290Sale2 items · contactless£6.10
16:13:52KingsmeadTill 2 · #5530Sale6 items · card£17.35
16:13:51Dorrick ParkTill 1 · #7214Sale2 items · cash£4.60

Holding offline

Since 15:31
Harlow Cross · Till 1Serving normally · link down14 held
#2208 → #2221Held on the register itself. Replayed into the book in sequence order when the link returns.

Stores

8 of 22 · by last write
StoreTillsLast write
Kingsmead4/40.4 s
Saltney Road3/31.2 s
Dorrick Park4/43.1 s
Wenlow Green3/34.0 s
Abbots Quay3/37.5 s
Harlow Cross3/49.8 s
Fenby Market2/212 s
Castle Mill3/315 s
and 14 more, all tills online

Who, what, and how long

Industry
E-commerce & Retail
Duration
22 weeks
Cooperation model
Dedicated team
Services
Platform engineeringInventory syncReporting
Integrations
ShopifyStripeKlaviyoShipStation
Technologies
ReactTypeScriptNode.jsPostgreSQLIndexedDBTailwind CSSGraphQL
Team
1 Delivery manager1 Product designer2 Frontend engineers1 Backend engineer1 QA engineer

Client name withheld under NDA. Engagement details are shown to the extent our agreement permits.

The problem

The hard problem

01
  1. 01

    Staff retyped data by hand and stock counts were rarely trustworthy by end of day, making reorder decisions guesswork.

    Stock was a number in one system and a different number in another, reconciled overnight, so from the moment the shop opened, both were wrong and neither knew it. Staff retyped deliveries into two places. By close of trade the counts were unreliable enough that reorder decisions were being made from the shelf instead of the screen.

    We built a single POS platform with shared inventory state, a fast checkout flow tuned for busy counters, and store-level reporting that updates as sales happen.

Introduction

The system we were asked to build

Registers, inventory, and reporting lived in separate tools that drifted out of sync. We built one POS platform with a shared source of truth across every store.

Twenty-two stores running registers from one vendor, a stock system from another, and a reporting spreadsheet assembled on Mondays. The three had been integrated by nightly file exchange, which worked until it didn't. The engagement was commissioned after a Christmas where the chain sold stock it didn't have in eleven stores and had to cancel the orders by hand.

Systems Integration

The solution

How the pieces fit

  1. 01

    Modeled one inventory source shared across registers and stores

    The chain had two stock figures reconciling overnight, so this step was mostly deciding which to keep. The answer was neither, since both were derived badly.

  2. 02

    Built an offline-tolerant checkout for unreliable store networks

    The register runs against a local database and treats the network as an enhancement, replaying transactions in order when the link returns.

  3. 03

    Shipped live store reporting for managers

    Managers were asked what they check on a Saturday afternoon, and the answer was three numbers on a phone behind a counter, which is what the board became.

  4. 04

    Migrated locations in waves with zero-downtime cutover

    Stores migrated in waves of four with the old system running in parallel until a full week reconciled. No store cut over on a successful test alone.

Offline-Tolerant Checkout Register

Keeps store registers ringing and processing transactions even during network outages.

The register runs entirely against IndexedDB and treats the network as an enhancement, so an outage at four on a Saturday doesn't stop the queue. Transactions are recorded locally with a monotonic sequence per register and replayed in order when the link returns; card payments fall back to the terminal's own store-and-forward. Nothing about the cashier's flow changes when connectivity drops. There's no offline mode to enter.

What shipped
  • IndexedDB-backed register; the network is optional
  • Per-register monotonic sequence, replayed in order
  • No offline mode to enter: the flow stays the same
RingboundDorrick ParkTill 2 No connection · 20 min · 9 held herePriya S.16:12
AllDairyBakeryPantryHome Scan or search
Oat milk1 L · Dairy£1.852
Whole milk2 pt · Dairy£1.35
Farmhouse cheddar350 g · Dairy£4.251
Greek yoghurt500 g · Dairy£2.40
Sourdough loaf800 g · Bakery£3.401
Butter croissants×4 · Bakery£2.60
Steel flask500 ml · Home£18.50
Beeswax wraps×3 · Home£6.001
Rapeseed oil500 ml · Pantry£2.95
Oatcakes300 g · Pantry£2.10
Seeded rolls×6 · Bakery£2.25
Ground coffee227 g · Pantry£4.75
Held on this till9 sales · £91.60 · none lost · written in order when the link returns
#447115:53£7.45
#447215:55£18.50
#447315:57£12.65
#447415:59£5.25
#447516:01£10.20
#447616:04£6.65
#447716:06£18.40
#447816:08£3.40
#447916:10£9.10
On screen

Twenty minutes with no connection at Dorrick Park: nine sales held on the register itself, none lost, and the next cart being served exactly as it would be online.

Stock on hand · Dairy

One figure per SKU per location, moved by every sale, refund, transfer and count as it happens

Six stores · DairySat 12 Sep 2026
Counted at
The till as it sells, not overnight
Lines out somewhere
4 of 12 dairy lines
Accuracy vs physical counts
99.2% first quarter · all 22 stores
Writes
Deltas never overwrites

On hand now

Units · each cell is one figure every register in that store reads
LineDORHARKNGSALWENABQSix
Oat milk 1 LDY-1041311238192217139
Whole milk 2 ptDY-100244265133029183
Semi-skimmed 2 ptDY-1005523047382734228
Farmhouse cheddar 350 gDY-1120149181181272
Crumbly Lancashire 300 gDY-113360743020
Greek yoghurt 500 gDY-108817112113101587
Natural yoghurt 500 gDY-109012715961059
Salted butter 250 gDY-1210231526181420116
Unsalted butter 250 gDY-121495064731
Double cream 300 mlDY-13021161385952
Clotted cream 227 gDY-133042503216
Free-range eggs ×6DY-1401362140271925168
Run out in that storeDOR Dorrick Park · HAR Harlow Cross · KNG Kingsmead · SAL Saltney Road · WEN Wenlow Green · ABQ Abbots Quay

Behind one figure

Oat milk 1 L · Kingsmead
On hand at Kingsmead38Same on 4 tills
TimeFromΔNow
15:58:00Carried23
15:58:12Till 2 · 5498−221
16:01:40Till 1 · 6352−120
16:03:05Till 3 · 6104−119
16:05:51Till 4 · 3310+120
16:07:22Till 2 · 5511−317
16:09:48Stock room · count−116
16:11:30Till 1 · 6370−115
16:13:02Till 3 · 6117−114
16:14:03Warehouse · T-881+2438
The warehouse transfer is a row in the same ledger as the sales. No separate adjustment.

Unified Inventory Pipeline

On screen

Dairy across six stores, counted at the register as it sells, never overnight, with the four lines that have run out somewhere, and the delta log behind one figure where a warehouse transfer sits in the same ledger as the sales.

Real-time stock synchronization across all retail stores and central warehouse.

Stock is one number per SKU per location, held server-side and pushed to every register over a subscription, so two stores can't both sell the last unit. Transfers between stores and the warehouse move through the same ledger as sales, with no separate adjustment path, which is what removed the monthly reconciliation. Counts write as deltas, never as absolute overwrites.

What shipped
  • One authoritative stock figure per SKU per location
  • Transfers and sales share one ledger, no side path
  • Deltas, never absolute overwrites

Live Store Manager Analytics

Instant reporting on hourly sales volume, top SKUs, and register performance.

Reporting reads from the same event stream the registers write to, so the hourly figure a manager sees is the sales themselves, not a nightly rollup of them. The board is built for a phone behind a counter: three numbers above the fold, top SKUs and register performance beneath, and a comparison against the same hour last week so a quiet afternoon can be read in context.

What shipped
  • Reads the live sale stream, never a nightly rollup
  • Three headline figures above the fold on a phone
  • Every figure compared against the same hour last week
16:40 82%
Dorrick ParkSat 12 Sep · 16:00–16:40 so farLive
Takings this hour£1,284.60+£112.50was £1,172.10
Sales this hour97+6was 91
Average basket£13.24+£0.36was £12.88
Top lines this hourunits
Oat milk 1 L38
Sourdough loaf21
Farmhouse cheddar14
Steel flask 500 ml6
Tills this houradd up to £1,284.60
Till 1£402.15 · 31
Till 29 replayed 16:13£318.40 · 24
Till 3£291.85 · 22
Till 4£272.20 · 20
On screen

The manager's board on a phone behind the counter: three figures for the hour so far, each against the same hour last week, then the top lines and the four registers that add up to the hour's takings.

Process

Phase by phase

  1. Phase 1: Hardware & Inventory Discovery

    Store Workflow & Stock Audit

    Audited register hardware, barcode scanners, and inventory drift across twenty-two stores.

    • Hardware Discovery Report
    • Inventory Architecture Spec
    • POS Migration Plan
  2. Phase 2: Offline-Tolerant Register Build

    IndexedDB Local Store Persistence

    Engineered a local IndexedDB persistence layer so registers operate continuously through network dropouts, syncing once reconnected.

    • Offline Register Engine
    • Local DB Sync Pipeline
    • Barcode Scanner Connector
  3. Phase 3: Central Inventory & Reporting

    Unified Stock API & Manager Dashboard

    Engineered unified inventory APIs and real-time store manager reporting dashboards for stock level and sale analytics.

    • Central Inventory API
    • Real-Time Manager Dashboard
    • Audit Trail Logging
  4. Phase 4: Multi-Store Wave Cutover

    Zero-Downtime Deployment & Training

    Migrated stores in planned waves of four with zero downtime, training store leads on new checkout and inventory workflows.

    • Wave Cutover Schedule
    • Store Staff Training Modules
    • Production Sign-off
RingboundDorrick ParkTill 4 · cashing up OnlineDev Mistry, store lead17:38

The drawer, note by note

Count what's there. The ledger already knows what should be.
Note / coinCountedValue
£502× £50£100.00
£2014× £20£280.00
£1019× £10£190.00
£516× £5£80.00
£221× £2£42.00
£138× £1£38.00
50p24× 50p£12.00
20p31× 20p£6.20
10p27× 10p£2.70
5p19× 5p£0.95
2p15× 2p£0.30
1p20× 1p£0.20
Counted in drawer£752.35

What the ledger already knew

Float at open, counted 07:58£150.00
Cash sales, net of change£602.35
Cash refunds£0.00
Expected in drawer£752.35
BalancedVariance £0.00

Card, from the terminal

Not counted
Card and contactless£1,846.30
Store cash-up6 min · was 30
Till 1Till 2Till 3Till 4
Close Dorrick Park for the day
On screen

Cashing up in six minutes instead of thirty: the drawer counted note by note against what the ledger already knew, balanced to the penny, with the card total taken straight from the terminal.

What it carries now

99.2%

Stock accuracy

+35%

Checkout speed

−80%

End-of-day reconciliation

Stock accuracy is measured against physical cycle counts across all twenty-two stores over the first quarter, not against the system's own figures. Checkout speed is median time from first scan to payment complete, sampled at comparable trading hours. Reconciliation time is the chain's own end-of-day labor figure per store.

Client name withheld under NDA. Figures are approximate, drawn from the engagement’s own reporting.

What the architecture settled

  • Shared single-source inventory brought store stock accuracy up to 99.2%.

    Accuracy came from removing the second number, not from syncing it better: two systems reconciling nightly are wrong for the whole trading day by construction.

  • Optimized counter checkout interface increased checkout speed by +35%.

    The checkout gain was mostly the network: a register that never waits on a round trip is faster at the counter than one that usually doesn't.

  • Automated end-of-day reconciliation reduced nightly register auditing time by 80%.

    End-of-day reconciliation collapsed because there was nothing left to reconcile. The ledger the register writes is the ledger the report reads.

How the work was run

  1. 01

    A cross-functional team of 5 worked on a dedicated team basis over 22 weeks, covering Platform engineering, Inventory sync, Reporting. We ran a weekly demo and kept a shared board open to check at any time. An in-house team took over day-to-day operation before the engagement ended, with handover built into the last phase.

    A dedicated team ran alongside the chain's own operations staff for the full twenty-two weeks, with a store manager in every review, held every two weeks. Migration went in waves of four stores with the old system live in parallel until each wave's figures reconciled for a full week. Nothing was cut over on the strength of a successful test.

Pull the cable on a till

The queue keeps moving. The book catches up, in order.

Three registers at Dorrick Park writing into one shared ledger, and Till 2 has already lost its connection. Ring up sales on any register, switch a connection off and on, and watch held sales replay in sequence while the stock figure moves on every register. Switch registers with the tabs, or the arrow keys once one is focused.

Dorrick Park · Till 2next sale #4473

Ring up a sale

Held on this till2 waiting for the link

  • #4471 Oat
  • #4472 Steel

Stock as each till sees it

LineT1T2T3Book
Oat milk 1 L22232222
Sourdough loaf11121111
Steel flask 500 ml6566

Amber is a register counting sales the book hasn't had yet.

The shared book3 writes

  • T1 #7214Oat milk 1 L −1
  • T3 #3028Sourdough loaf −1
  • T1 #7213Oat milk 1 L −1

Why nothing is lost: the register writes every sale to its own database first and treats the network as an enhancement, so there's no offline mode to enter. Goods, stock levels and the replay pacing here are illustrative.

Architecture

From one scan to the same number on every register

The ledger the register writes is the ledger the report reads. There's no second stock figure to reconcile overnight, and no nightly file exchange between a register, a stock system and a spreadsheet.

  1. 01 · Trigger
    A scan at the tillThe register runs entirely against IndexedDB, so a sale is recorded on the register before the network is asked for anything.
  2. 02 · Queue
    Per-register sequenceEach register numbers its transactions monotonically and replays them in order when the link returns. Card payments fall back to the terminal's store-and-forward.
  3. 03 · Engine
    Unified stock APISales, refunds, counts and transfers between stores and the warehouse move through one path, written as deltas and never as absolute overwrites.
  4. 04 · State
    One ledger in PostgreSQLOne authoritative stock figure per SKU per location, held server-side, so two stores can't both sell the last unit.
  5. 05 · Delivery
    Subscriptions to registers and phonesEvery register has the figure pushed over a subscription, and the manager's board reads the same event stream, with no nightly rollup.

What a Saturday afternoon can throw at it

Outages, oversells & cutover

A dropped link doesn't stop the queue

The register records every sale locally with its own sequence number and replays them in order when the connection returns. Card payments use the terminal's store-and-forward, and there's no offline mode for staff to enter.

Two stores can't sell the same last unit

Stock is one figure per SKU per location, held server-side and pushed to every register. Transfers go through the same ledger as sales, and counts write as deltas, so nothing overwrites anything else.

No store cut over on a passing test

Stores moved in waves of four with the old system running in parallel, and nothing was cut over until that wave's figures had reconciled for a full week.

Registers, stock and reporting that disagree by lunchtime? Scope your build in 3 minutes.

Scope your build
Have a project?

Let's talk

Running a large platform, shaping a first MVP, or getting a product ready for a funding round? Tell us where you are. We'll shape the process around it, and stay with you after launch.