Subscription & Payment Manager
A full-stack SaaS for running subscription businesses: customers, tiered plans, billing and Razorpay payments behind role-based access. I built it to go deep on the hardest parts of payments: webhook reliability, signature verification, and never applying a payment twice.
- React
- Node.js
- Express
- PostgreSQL
- Razorpay
- JWT
Particulars
- Type
- Independent project, open source
- Role
- Sole designer and full stack engineer
- Payments
- Razorpay, webhook-driven
- Scope
- Auth, RBAC, subscriptions, billing and payments
01The mandate
Taking a payment is easy. Keeping subscription state correct when payment events arrive late, twice or out of order is not. I wanted a project where that problem was the point, wrapped in a product with real roles, plans and billing around it.
02What I owned
All of it. I designed role-based access for multiple user types, implemented authentication and protected workflows, built tier-based subscription and billing flows, and integrated Razorpay with webhook-driven payment updates.
I designed the backend APIs across authentication, users, subscriptions and payments, built the subscription management UI, added caching for frequently read data, and refactored modules as the system grew.
03Webhooks as the source of truth
The browser can say a checkout finished; only Razorpay can say a payment was captured. Subscription state changes on verified webhook events: each signature is checked against the shared secret, and processing is idempotent, so a retried or duplicated event can never apply twice.
Fig. 01
04Working flow
The full path of a subscription payment. The client starts checkout, but only a verified webhook can change what a customer has paid for.
Fig. 02
01 Chooses a plan
02 Requests an order (JWT)
03 Creates the order for the plan amount
04 Order ID
05 Order ID
06 Opens checkout; the customer pays
07 Signed webhook event
- 08 Verifies the signature, checks the event isn't already applied
09 Records the payment once, activates the subscription
10 Refreshes subscription status
11 Active plan and access
05Hard parts
- Making duplicate and retried webhooks safe through idempotent processing.
- Never trusting a payment event before verifying its signature.
- Role-based access across multiple user types, enforced consistently in the API and the UI.
- Caching frequently read data without serving stale subscription state.
06Outcomes
- A working subscription platform covering plans, billing and payments end to end.
- Payment processing that is verified and duplicate-safe by design.
- Tier-based plans and billing workflows behind role-based access.
07How I approached it
- 01
Trust the processor, verify the message
Payment state comes from signed events, not the client.
- 02
Design for retries
Anything delivered over the network will eventually arrive twice.
- 03
Permissions are architecture
Roles were modelled up front, not patched in per screen.
- 04
Refactor as it grows
Modules were reshaped as the domain became clearer.
Related work
More projectsKurlClub
SaaS platform, React, Next.js, TypeScript
HR Platform
Enterprise HR, React, Node.js, JWT
BFC Pay
FinTech, React, Node.js, Rust
HI5 Overseas
Client application, Next.js, TypeScript, Node.js
