Cashpad — Rails Backend · CTO Overview

Cashpad
Backend
Engineering

Cashpad is a 100% French iPad-native POS platform dedicated to the restaurant industry — brasseries, fast-food chains, hotel restaurants, corporate catering. As a backend Rails engineer I contributed to the core transactional engine, the multi-site centralisation layer, the decentralised offline architecture, and bespoke enterprise integrations including the BETC group corporate catering system.

7+
Countries deployed
7500
Tickets/day per site
100%
Offline resilient
3×
Faster than legacy POS

Rails API · PostgreSQL · Redis · offline-first iOS

The Cashpad backend is a Ruby on Rails JSON API that serves a fleet of iPad POS terminals and a web-based back-office. The system is designed for internet-free resilience: terminals carry a local SQLite database that queues all transactions, syncing to the central PostgreSQL server when connectivity is available. The Rails monolith handles menu configuration, multi-site synchronisation, analytics, webhooks to third-party services, and bespoke enterprise integrations.

Cashpad System Architecture — Rails API + iPad POS Ruby on Rails · PostgreSQL · Redis
Clients
iPad POS (iOS)
Cashpad native app · local SQLite · offline queue
iPhone/Android mobile
Tap to Pay · tableside ordering
Back-office (web)
Rails views · multi-site dashboard
Edge
Nginx
TLS · rate-limiting · reverse proxy
Local LAN sync
iPad ↔ iPad peer sync on site LAN — zero internet needed
App
Rails API (Puma)
JSON:API · multi-tenant · menu sync · analytics
Sidekiq
Async sync jobs · webhook delivery · reporting
KDS Engine
Kitchen Display System · ActionCable · real-time orders
Services
Stripe / TPE
Card payments · cashless · tap-to-pay
UberEats · Deliveroo · Glovo
Delivery platform ingestion via webhooks
Accounting connectors
Export to Sage, EBP, Quadratus
Data
PostgreSQL (central)
Canonical transaction store · multi-tenant schemas
SQLite (local, iPad)
Decentralised offline store · conflict-resolution on sync
Redis
Sidekiq · ActionCable pub/sub · cache

The transactional core — tickets, menus, fiscal compliance

The heart of the Rails backend is the transaction engine: ticket creation, order routing to kitchen zones, table/seat management, formula recognition, tip handling, multi-payment splits, and NF525 fiscal certificate compliance. Every ticket is an immutable PostgreSQL record with a full audit trail — legally required by French fiscal law.

🧾
NF525 Fiscal Compliance
Immutable ticket chains with cryptographic chaining. Every ticket references its predecessor — tamper-evident by design. Rails model callbacks enforce the chain at write time.
🍽️
Formula Auto-Recognition
Complex menu formula detection (entrée + plat + dessert → menu price) resolved in pure Ruby at order-line insertion. No client-side price logic — server is the single source of truth.
📺
Kitchen Display (KDS)
ActionCable WebSocket channel pushes order lines to KDS screens in real time. Rails pub/sub via Redis — sub-100 ms kitchen notification from order submission.
💳
Multi-payment & Split
Arbitrary bill splits (by seat, by product, fractional), mixed payment methods (card + cash + voucher) resolved by a dedicated PaymentSession model with PostgreSQL row-level locking.
🏪
Multi-site Centralisation
Menu pushes from HQ to all sites in a single Rails job. Site-specific price overrides, local products, and VAT rates handled via a layered configuration model with inheritance.
📦
Delivery Platform Ingestion
UberEats, Deliveroo, Glovo webhooks normalised into the same internal Order model. Sidekiq consumer parses, validates, and injects as if from a POS terminal — zero UI change for kitchen staff.

Decentralised database — 100% operational without internet

A restaurant's internet connection failing during a dinner service is a catastrophic event. Cashpad eliminates this risk through a decentralised database architecture: each iPad holds a full local SQLite store and continues processing transactions independently. Synchronisation to the central PostgreSQL server happens opportunistically and is designed to be conflict-resilient.

01
Local-first writes
Every ticket, order line, and payment is written to the iPad's local SQLite database first — before any network call is attempted. The terminal is always the primary store during service.
SQLite local
02
LAN peer-to-peer sync
iPads on the same LAN sync their local stores with each other over the local network — no internet needed. Table status, ticket state, and order routing are consistent across all terminals on-site even when the WAN is down.
LAN sync
03
Async push to central PostgreSQL
When internet is available, a Sidekiq job on each terminal pushes its pending transaction log to the central Rails API. Transactions are idempotent — safe to retry. The server applies them to PostgreSQL and acknowledges with a server-side UUID.
PostgreSQL sync
04
Conflict resolution
Conflicts (e.g., concurrent table status updates from two iPads) are resolved by a vector-clock approach on the Rails model. Last-writer-wins for non-fiscal data; for tickets, the NF525 chain takes precedence and the server is canonical.
vector clock
05
Menu config pull
On connectivity restoration, the terminal pulls the latest menu configuration diff from the central API. Delta payloads (only changed items) keep sync payloads small even for large menus.
delta sync
Engineering note
This architecture was the most technically demanding aspect of the backend. The challenge isn't the happy path — it's the recovery from partial syncs, clock drift between iPads, and the fiscal constraint that ticket sequences must be gapless. The solution required careful use of PostgreSQL advisory locks and a dedicated reconciliation job that runs nightly to verify chain integrity across all sites.

BETC Group — Corporate Catering System

One of the most architecturally interesting integrations was the bespoke catering management system built for BETC — the renowned French advertising agency (Air France, Canal+, Evian, Louis Vuitton, Peugeot…) with 750+ employees at their Les Magasins Généraux campus in Pantin. The corporate restaurant required a fundamentally different model from a public-facing brasserie: cashless, badge-authenticated, employer-subsidised meals, and real-time reporting to HR and payroll.

01
Dallas key / badge authentication
Each BETC employee identified by NFC badge or Dallas key on the POS terminal. Rails API validates against the HR employee directory via a secure LDAP bridge.
LDAP
02
Cashless employer-subsidy model
Meal cost split between employee wallet (pre-loaded monthly) and employer subsidy. Rails calculates the net employee charge at ticket close, applying lunch-voucher equivalent rules.
subsidy engine
03
Decentralised multi-counter setup
The BETC canteen has multiple serving counters operating as independent POS nodes on a LAN. Each node has its own SQLite local store, syncing to a dedicated on-premise PostgreSQL instance — no cloud dependency for daily operations.
on-premise
04
HR / payroll export
Monthly Rails job generates per-employee meal reports exported to BETC's payroll system (CSV + API). Each employee's net meal deduction is computed from the consolidated PostgreSQL ledger.
payroll API
05
Dietary preference tracking
Employee profiles store allergen flags and dietary preferences. Menu items tagged accordingly — kitchen display highlights special requirements for each order.
profile flags
🏢 BETC in context
BETC is France's most creative advertising agency 13 years running — 750 staff across their Pantin campus, managing global accounts including Air France, Canal+, Evian, Louis Vuitton, Lacoste, Peugeot, L'Oréal, and McDonald's. The canteen serves hundreds of meals daily across multiple counters, with zero tolerance for downtime. The decentralised offline architecture was a strict requirement, not a nice-to-have.
On-premise PostgreSQL node
Unlike the standard Cashpad cloud deployment, the BETC integration runs a dedicated Rails instance on-premise at Les Magasins Généraux. The central PostgreSQL node lives in BETC's server room, with daily encrypted backup to the Cashpad cloud. This meets BETC's data residency requirements while keeping the architecture consistent with the standard Cashpad codebase — the same Rails models, with a tenant-specific configuration.
Employees served daily 750+
POS counters (LAN nodes) 4–6 concurrent
Offline resilience 100% LAN-first
Data residency On-premise · Paris

Centralised analytics · multi-site dashboards

The Rails back-office gives operators real-time visibility across all their sites from a single interface. The reporting layer aggregates transaction data from every POS node into PostgreSQL, then exposes it via a REST JSON API consumed by the web dashboard and exportable to accounting software.

Report moduleDescriptionRails implementation
Real-time salesLive revenue per site, per category, per server — updates every 60 sSidekiq scheduler + PostgreSQL materialised view
Cross-site comparisonSide-by-side KPI comparison across franchise/network sitesMulti-tenant scoped ActiveRecord + Chart.js API
Product-level analyticsBest/worst sellers, margin by item, cover counts by time slotPostgreSQL window functions via Arel
Server performancePer-server ticket count, average ticket value, tip rateGrouped aggregates + Pundit role scoping
Accounting exportDaily Z-report, VAT breakdowns, payment method totalsCSV/PDF export via Prawn + background Sidekiq job
Menu deploy logAudit trail of all menu pushes: who changed what, when, on which sitesActiveRecord PaperTrail gem + diff renderer

Open ecosystem · delivery · accounting · loyalty

A key part of the Rails backend's value is its open integration ecosystem. The same Order model that accepts a ticket from a POS terminal also accepts orders from UberEats, a self-order kiosk, or a QR-code table. The same payment engine processes cash, Stripe, and employer-subsidy wallets.

🚴
Delivery Platforms
UberEats, Deliveroo, Glovo, Stuart webhook consumers. Normalised to internal Order model — kitchen sees one unified queue regardless of source.
📊
Accounting Software
Sage, EBP, Quadratus, Pennylane. Daily export jobs generate accounting-ready files in the correct format per client configuration.
📱
Click & Collect / QR
Self-service ordering via QR code or kiosk routes through the same Rails API. Payment via Stripe Checkout; order injected directly to kitchen queue.
🏦
Cashless & Tap to Pay
Stripe Terminal (tap-to-pay on iPhone) and cashless wallet systems (corporate, event). Payment captured via Stripe webhooks, reconciled against ticket ledger.
🍷
Stock & Cellar Management
Wine cellar stock sync — depletion triggered by ticket line items. Rails ActiveRecord callbacks update stock levels; reorder threshold alerts via Sidekiq.
🔑
Dallas Key Auth
Staff authentication via Dallas key touch on POS hardware. Rails validates the key ID against the staff table — role-based access (server, manager, admin) applied in Pundit.

Major clients & reference accounts

Cashpad serves a diverse portfolio spanning independent brasseries, fast-food chains, hotel groups, franchise networks, and enterprise corporate catering. The Rails backend is configured per-tenant and scales from a single neighbourhood restaurant to a multi-country franchise network.

Client / GroupSegmentIntegration
BETC (Havas)Corporate catering · 750 staffCustom on-premise
Crêpe TouchFranchise network · nationwideMulti-site central
Italian TrattoriaMulti-site chainCentral deploy
HippopotamusSteak restaurant chainPOS + KDS
Groupe SALPAFine dining · AlsacePOS + back-office
Krispy Kreme FranceQSR · kiosk integrationKiosk + POS
Léon de BruxellesCasual dining chainMulti-site
Brioche DoréeFast-casual bakery chainPOS + click&collect

Additional reference clients across segments:

Hippopotamus
Brioche Dorée
Léon de Bruxelles
Buffalo Grill
Courtepaille
Autogrill
Krispy Kreme France
Italian Trattoria
Groupe SALPA
Pizza Thaï
Newreest
Au Crocodile
Hôtels Novotel
+200 independents
Distribution
Cashpad is distributed in 7 countries, primarily France, Belgium, Switzerland, and Morocco. The multi-tenant Rails architecture handles all locales — TVA rate tables, currency formatting, fiscal rule variants — from a single codebase.

Debian Linux · multi-tenant PostgreSQL · high availability

The production stack mirrors the OAM platform's hardening philosophy: Debian LTS, Nginx reverse proxy, Puma, Sidekiq, Redis, with PostgreSQL multi-tenant schemas per franchise network and dedicated databases for enterprise on-premise clients like BETC.

🐧
Debian LTS
Minimal hardened install. Unattended security upgrades. fail2ban, UFW, SSH key-only auth.
🗄
PostgreSQL multi-tenant
Schema-per-network for franchise groups. Database-per-tenant for enterprise on-premise. Nightly pg_dump to encrypted S3.
Redis + Sidekiq
Background job queues for sync, exports, webhook delivery. Priority queues: fiscal jobs highest priority.
🔒
Security
Brakeman in CI, Rack::Attack rate-limiting, Rails encrypted credentials, NF525 audit trail, RGPD-compliant data handling.
Cashpad · cashpad.io · Backend Engineering
Ruby on Rails · PostgreSQL · Offline-first iPad POS · France + 7 countries
Ruby on Rails PostgreSQL Offline-first NF525 Compliant
Menu