NexPay — Multi-Tenant Payment Infrastructure
Production-grade payment platform implementing the full payment lifecycle, double-entry accounting ledger, wallet balances, fraud scoring, subscription billing, webhooks, disputes, payouts, and daily reconciliation.
Domain Knowledge
What problem this project solves
Payments are a distributed-consistency problem: money must never be lost or double-spent, even when networks fail mid-transaction. NexPay treats every movement of money as a state transition in a strict state machine with idempotent operations. The double-entry ledger guarantees accounting invariants hold, the outbox pattern guarantees webhook delivery, and daily reconciliation catches drift between payment records and ledger balances.
Architecture
How the system is structured
A Turbo monorepo with three apps — an Express REST API, a merchant portal, and an admin portal — plus shared packages and a TypeScript SDK. The API is organized into 34 feature modules backed by 6 BullMQ workers (billing, fraud-unblock, outbox, payout, reconciliation, webhook). Middleware enforces JWT auth with RBAC, idempotency keys (Redis lock + Prisma), Prometheus metrics, per-endpoint rate limiting, and request tracing.
Data Model
Schema design and data flow
60+ Prisma models covering merchants, customers, payment methods, payment state machines, ledger accounts and entries, wallets, invoices, subscriptions, disputes, fraud rules, webhooks, payouts, and reconciliation runs. Account types follow double-entry conventions: Asset, Liability, Revenue, Expense, Reserve.
Key Challenges
Hardest problems encountered
The hardest problems were payment state consistency (a payment can be captured, refunded, disputed, won, or lost — each transition must be atomic and idempotent), preventing double-charging under retries via idempotency keys, fraud scoring that adapts per merchant, and keeping the ledger balanced under high concurrency using advisory locks.
Scaling Strategy
How the system grows
BullMQ distributes background work across 6 workers with retry and dead-letter queues. Redis caches hot paths and backs rate limiting. The reconciliation worker runs daily and the outbox worker guarantees event delivery. Docker Compose supports dev, production (with Nginx, Prometheus, Grafana), and e2e environments.
Security
Defense-in-depth approach
JWT authentication with RBAC, TOTP MFA, sandbox mode for testing, idempotency enforcement, per-endpoint rate limiting, HMAC-signed webhooks, tenant-scoped data access, and full audit logging.
Failure Handling
Resilience and recovery
Webhook delivery uses exponential backoff with a dead-letter queue. Payments are idempotent so duplicate requests never double-charge. The fraud-unblock worker resolves time-based flags automatically. Reconciliation detects ledger drift daily.
Observability
Monitoring and debugging
Prometheus metrics, Pino structured logging with request IDs, and a metrics module. 22 test files cover ledger invariants, tenant isolation, payment state transitions, refunds, reconciliation, and webhook delivery.
Trade-offs
Engineering decisions and alternatives
PostgreSQL + Prisma for relational integrity over NoSQL. BullMQ over in-process queues for durability and observability. A monolith API over microservices at this scale. Gateway adapters (Mock, Stripe, Razorpay) over a single vendor.
Architecture Decisions
Key choices and what was rejected
Senior-Level Topics
Concepts this project explores