Recurring billing engine for Nigeria. Subscription state machine, dunning loop, proration math, Nomba payments, PDF invoicing. Next.js monolith.
# NomSubz
**A managed recurring-billing engine built on top of Nomba's payment primitives.**
NomSubz wraps Nomba's Checkout, Tokenised Cards, Charge API, and Transfers into a full subscription-management layer, so downstream product teams can offer recurring billing without building state machines, dunning logic, or proration math themselves.
---
## Features
- ๐ **Subscription state machine** โ `incomplete โ active โ past_due โ paused/canceled`
- ๐ณ **Tokenized card billing** via Nomba's Charge API
- ๐ **Dunning loop** โ automatic retries and email notifications on failed payments (Day 1 / Day 3 / Day 7)
- โธ๏ธ **Delayed pause** โ users keep access until the end of their paid period
- ๐งฎ **Accurate proration** โ `decimal.js`-based math with defensive clamping, no floating-point drift
- ๐งพ **Invoices & PDFs** โ generated on the fly
- ๐ **Secure by design** โ HMAC-verified webhooks, hashed server-to-server API keys
- ๐ **Webhook registration** โ downstream products can subscribe to engine events
---
## Tech Stack
| Layer | Choice |
| --------------- | ------------------------------------------------------------------- |
| Framework | Next.js (Node.js / TypeScript monolith) |
| Database | PostgreSQL |
| Background Jobs | `pg-boss` (SQL-backed queue, avoids Redis cache-eviction conflicts) |
| Scheduler | Lightweight DB-backed cron / event-driven trigger |
| Payments | Nomba (Checkout, Tokenised Cards, Charge API, Transfers) |
---
## Database Schema
The core of the engine is the `subscriptions` table:
```sql
CREATE TABLE subscriptions (
id SERIAL PRIMARY KEY,
customer_id VARCHAR(255) NOT NULL,
plan_id VARCHAR(255) NOT NULL,
status VARCHAR(50) NOT NULL, -- 'active', 'past_due', 'paused', 'canceled'
current_period_start TIMESTAMP WITH TIME ZONE NOT NULL,
cur โฆ