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
System Architecture
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 POSRuby 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
POS Transaction Engine
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.
Offline Resilience & Sync
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.
Enterprise Integration
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.
Architecture specifics
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.
BETC system KPIs
Employees served daily750+
POS counters (LAN nodes)4–6 concurrent
Offline resilience100% LAN-first
Data residencyOn-premise · Paris
Back-office & Reporting API
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 module
Description
Rails implementation
Real-time sales
Live revenue per site, per category, per server — updates every 60 s
Sidekiq scheduler + PostgreSQL materialised view
Cross-site comparison
Side-by-side KPI comparison across franchise/network sites
Multi-tenant scoped ActiveRecord + Chart.js API
Product-level analytics
Best/worst sellers, margin by item, cover counts by time slot
PostgreSQL window functions via Arel
Server performance
Per-server ticket count, average ticket value, tip rate
Audit trail of all menu pushes: who changed what, when, on which sites
ActiveRecord PaperTrail gem + diff renderer
Third-party Integrations
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.
Client Portfolio
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 / Group
Segment
Integration
BETC (Havas)
Corporate catering · 750 staff
Custom on-premise
Crêpe Touch
Franchise network · nationwide
Multi-site central
Italian Trattoria
Multi-site chain
Central deploy
Hippopotamus
Steak restaurant chain
POS + KDS
Groupe SALPA
Fine dining · Alsace
POS + back-office
Krispy Kreme France
QSR · kiosk integration
Kiosk + POS
Léon de Bruxelles
Casual dining chain
Multi-site
Brioche Dorée
Fast-casual bakery chain
POS + click&collect
Additional reference clients across segments:
BETC (Havas)
Crêpe Touch
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.
Infrastructure
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.