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.

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.
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.
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
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.