All case studies
Own product · SaaS · Loyalty · 2026

Nujoomy — Multi-Tenant Loyalty SaaS

My own SaaS product: a multi-tenant loyalty platform issuing live Apple Wallet and Google Wallet cards, with QR redemptions and a partner API.

3 min read
NestJSNext.jsPostgreSQLRedisBullMQApple WalletGoogle WalletPaymob
Nujoomy — Multi-Tenant Loyalty SaaS
Apple + Google
Wallet cards
Multi-tenant
Tenancy
Partner API
Access

The problem

Small businesses want a loyalty program, but the off-the-shelf options are either paper stamp cards or heavy enterprise suites. The interesting constraint is the card itself: customers expect a real wallet pass that updates the moment they earn or redeem — not a screenshot that goes stale.

So the platform had to do three things well at once: be multi-tenant (every business runs its own branded program), issue live wallet passes to two ecosystems, and stay correct when a single QR scan triggers a cascade of side effects.

The architecture

A NestJS backend owns the domain; Next.js serves the tenant dashboards and the staff scanning UI. PostgreSQL is the source of truth, Redis backs the queues, and BullMQ runs every side effect off the request path.

Earn / redeem flow

Why queues, not inline work

A redemption is one user action with several consequences: update the balance, push a new pass to the wallet, notify the customer, and fan out to any partner integrations. Doing that inline makes the scan slow and couples its success to Apple's and Google's uptime. Pushing each consequence onto BullMQ keeps the scan instant and lets every side effect retry independently.

Multi-tenancy and the partner API

Every record is tenant-scoped, and the platform exposes a B2B partner API with separate authentication planes — live and test keys, per-key rate limits, idempotency keys, and HMAC-signed webhooks — so partners can integrate without ever touching another tenant's data.

Wallet passes are a sync problem

The hard part isn't generating a pass — it's keeping thousands of issued passes in sync. Each balance change enqueues a targeted pass-update job, so the card in a customer's wallet reflects reality without them reopening the app.

Outcomes

Apple + Google
Live wallet cards
Passes that update on each earn / redeem
Multi-tenant
Per-business programs
Branded, isolated, self-serve
Partner API
Live + test keys
Idempotent, rate-limited, HMAC-signed

What this taught me

Loyalty looks simple until the card has to be live. The engineering value is in the plumbing around the reward — tenant isolation, a clean ledger, and queues that make wallet sync and partner fan-out reliable instead of best-effort.

Building something similar?

Send a quick note — happy to compare notes on the architecture.