Multi-tenant retail POS SaaS
A multi-tenant POS for retail — product item scheduling, happy-hour pricing models, split-payment logic and PIN-secured granular RBAC. Co-architected at SELISE Digital Platforms.
- Live
- Multi-tenant
- 5-role PIN RBAC

By the numbers
- Tenancy model
- Multi
- Role tiers
- 5
- Login method
- PIN
- Payment flows
- Split
01The problem
Multi-branch retail and hospitality teams run on hardware tills, paper schedules, and POS systems that treat every venue as a separate install. Adding a happy-hour rule across ten branches is a ten-branch job; splitting a single check across multiple payment methods drops to spreadsheet workarounds; PIN-switching between cashier and manager roles is either non-existent or a security hole. The brief was to build a single multi-tenant SaaS where one operator runs many venues — with full data isolation between tenants, happy-hour rules scheduled per tenant, split payments handled cleanly, and PIN-secured role switching that an audit team can trust.
02What we built
- 01
A full multi-tenant data isolation layer using PostgreSQL schemas — every query scopes through a tenant boundary and there is no path for one venue's data to bleed into another's.
- 02
A happy-hour pricing engine with configurable time windows per tenant — every product can be scheduled in/out of pricing rules without redeploys or per-venue overrides.
- 03
Split-payment flows across multiple payment methods on a single check — cash + card + gift, with reconciliation logged into a per-tenant payment ledger.
- 04
Granular Role-Based Access Control with PIN-secured role switching — cashier, supervisor, manager and admin tiers, per-tenant permission overrides, and an audit trail on every role escalation.
- 05
An Angular 20 cashier UI built on standalone components and a signal store, so the terminal stays responsive at high throughput and updates flow through without re-renders that cost a sale.
- 06
A tenant onboarding flow that provisions a fresh PostgreSQL schema, seeds the default role set, and lets an operator spin up a new venue from the admin console without engineering touching it.
03Stack
Cashier + manager
- Angular 20
- TypeScript
- RxJS
- Reactive forms
- Standalone components
- Signal store
- Material
- Tailwind
Tenant admin
- PIN session
- 5-role RBAC
- Per-tenant role config
- Audit log
- Tenant onboarding
- Schedule editor
- Pricing window editor
- Split-payment console
Data + pricing engine
- PostgreSQL schemas
- Tenant isolation
- Drizzle / TypeORM
- Happy-hour engine
- Split-payment ledger
- REST + DTO validation
- JWT + refresh
- Audit trail
04The hard part
The hardest part was making multi-tenancy real all the way down to the schema, while keeping the cashier UI fast enough to use during a rush. PostgreSQL schemas gave clean tenant isolation, but every query path had to scope through the tenant boundary without bolting on a heavy ORM layer that would cost milliseconds at the terminal. The pricing engine had to fold happy-hour windows into the cart calculation without a server round-trip on every tap, which meant pushing time-window logic to the client with a single contract-tested source of truth on the server.
The second hard part was the PIN-secured role switch. A POS terminal stays logged in to a venue all day, but cashiers, supervisors and managers all touch it within a single transaction — a manager approving a discount, a supervisor authorising a void, a cashier completing the sale. Switching roles couldn't mean logging out; it had to be a PIN-bound escalation tied to a per-tenant role policy, with an audit row written on every step. That meant role authority lives at the session level, but every privileged action checks the live policy — and the audit trail names the human who triggered it.
Your move
Want one built around your operation?
We take on a small number of custom engagements per year. If this looks close to a problem you have, tell us about it.