Eshop
A storefront that agrees with the till.
A POS-connected online store: delta sync against OneHubPOS, two payment gateways, magic-link SSO, multi-tenant access control, and a dual-table design so a merchant's own customisations survive the next sync from the point of sale.
- 4 locations
- one system, one catalogue
- 80% fewer
- POS API calls after delta sync
- 2 gateways
- NMI and Dejavoo
The problem
The POS owns the catalogue, and the merchant wants to change it
Menus, prices, taxes and modifiers all live in the point of sale, and it overwrites on every sync. But a merchant wants better photographs, longer descriptions and web-only items. Store those in the same rows and the next sync erases them. Store them nowhere and the online store reads like a spreadsheet. Most integrations in this category land on one side of that trade or the other.
How it was built
In order, and why.
01
Map the POS
What it emits, how often, what it silently omits, and what it does on a delete. Integration work fails on assumptions about the other system, so this came before any code.
02
Two tables, one product
POS data lands in immutable reference tables the sync owns completely; merchant customisations live in a parallel table keyed to the same product. The read layer merges them, so a sync can never clobber a custom description or image.
03
Payments and identity
Two gateways for routing and redundancy, and magic-link SSO so staff across locations sign in without another password to forget or leak.
04
Sync and reconcile
A background worker runs timestamped delta syncs on a per-store schedule with retries and backoff, orders push back to the POS automatically, and reconciliation reports anything the two sides disagree about.
The part that was actually hard
Making a sync that cannot destroy someone's work
The tempting design is one products table with the sync doing an upsert. It is simpler and it is wrong: the first time a merchant writes a good description, the next sync removes it. Splitting ownership at the field level — immutable POS-owned rows the sync controls entirely, merchant-owned rows it never touches, merged on read — lets the sync stay aggressive and simple, which is what a sync should be. The second half was doing that across four stores without hammering the POS API, which is what timestamped delta sync solved.
POS-owned
- Price
- Tax
- Modifiers
- Stock
Sync overwrites freely
Merchant-owned
- Description
- Photography
- Web-only items
- SEO copy
Sync never touches
What it does
The features that carry it.
01
Delta sync
Changed records only, on a per-store schedule with retries and backoff. Fetching just what moved since the last run cut POS API traffic by roughly 80% while keeping the catalogue fresh.
02
Dual-table architecture
Merchant customisations live beside POS-owned data rather than inside it, so a sync overwrites what it should and nothing else.
03
Two payment gateways
NMI and Dejavoo, with routing between them, so a single processor problem is not a closed store.
04
Magic-link SSO
Keycloak-backed passwordless sign-in for staff across locations, which removes the shared-password problem that multi-site retail always has.
05
Multi-tenant RBAC
Three roles scoped per location across four stores, enforced server side rather than by hiding navigation.
06
Reconciliation
Scheduled comparison between the storefront and the POS, naming the records that disagree rather than counting them.
Outcome
What actually changed.
01
80% fewer POS API calls
Timestamped delta sync replaced full catalogue reloads, fetching only what changed since the last run while keeping four stores current.
02
Merchant work survives the sync
Descriptions, photography and web-only items live in rows the sync never touches, so the aggressive sync and the merchant's edits stopped being in conflict.
03
Four locations, one catalogue
Per-store scheduling with retries and backoff, and orders pushing back to the point of sale automatically rather than being re-keyed.
In hindsight
What we would do differently.
The reconciliation job shipped after launch rather than with the first sync. Its first run surfaced three weeks of accumulated drift — all of it recoverable, none of it detected until then, and none of it visible to anybody in the meantime. Reconciliation is a day of work and it should be part of the first integration, not an improvement you make once you already trust the system.
Built with
The stack underneath.
- Application
- React, Node.js, TypeScript
- Data
- PostgreSQL, Redis, delta sync, reconciliation
- Payments
- NMI, Dejavoo gateway routing
- Identity
- Keycloak, magic-link SSO, multi-tenant RBAC
Where it stands today
Shipped and running. This is the build the POS and payments pages on this site are describing when they talk about idempotent writes and reconciliation — it is where those opinions came from.
Practice areas this evidences
Want something like this
This is bought as one of these.
Fixed-price project
Ecommerce & POS
Fixed-price project
Selling online and over a counter, with one stock number behind both. Terminals, printers, card readers and the reconciliation that keeps them honest.
Fixed-price project
Systems Integration
Fixed-price project
Making the systems you already pay for agree with each other, so nobody is retyping between them at five o'clock.
Fixed-price project
Web Applications
Fixed-price project
Customer portals, operational dashboards, booking systems and internal tools. The things a spreadsheet used to do until it stopped coping.
Tell us what you’re trying to build.
If something here looks like the problem you have, say so and we’ll tell you how close it actually is.
Phone
+1 (407) 796-2376Reply time
One business day, from an engineer
Based in
Orlando, Florida · serving the United States
What happens next
- A reply within one business day, from an engineer
- A thirty-minute call, with no qualifying call before it
- A written scope and a fixed number, if it fits