A robust, production-ready backend API for managing subscriptions with automated email reminders, rate limiting, and bot protection.
Architecture β’ Features β’ API Endpoints β’ Getting Started β’ License
SubDub is a secure, production-grade Subscription Management API designed to handle users, subscriptions, and smart automated renewal notifications. Built on Node.js and Express, it integrates MongoDB for persistence, Arcjet for bot protection/rate limiting, and Upstash Workflow for reliable background job execution and smart email dispatching.
- Runtime Environment: Node.js (ES Modules)
- Backend Framework: Express.js
- Database: MongoDB (using Mongoose ORM)
- Security & Shielding: Arcjet (Rate limiting, Bot detection, Content shielding)
- Background Jobs & Workflows: Upstash Workflow
- Email Delivery: Nodemailer
- Authentication: JSON Web Tokens (JWT) & bcryptjs
- Development Tooling: Nodemon, ESLint, MongoDB Memory Server (for local development fallback)
SubDub is structured with scalability and security at its core. Below are the architectural workflows detailing how client requests are processed and how automated email alerts are triggered.
Every incoming request passes through security middleware before reaching API routes and database layers.
sequenceDiagram
autonumber
actor Client
participant Express as Express.js Router
participant Arcjet as Arcjet Middleware
participant Auth as Auth Middleware
participant Controller as Controller
participant DB as MongoDB (Mongoose)
Client->>Express: Send API Request
Express->>Arcjet: Pass to Arcjet (Shield, Rate Limit, Bot Check)
alt Request Denied
Arcjet-->>Client: 429 Too Many Requests / 403 Forbidden
else Request Approved
Arcjet->>Express: Continue Request
opt If Route Requires Authentication
Express->>Auth: Validate JWT
alt JWT Invalid/Missing
Auth-->>Client: 401 Unauthorized
else JWT Valid
Auth->>Express: Attach User details
end
end
Express->>Controller: Route to controller action
Controller->>DB: Database Query (Read/Write)
DB-->>Controller: Return Document/Data
Controller-->>Client: Send JSON Response
end
When a user creates a subscription, an asynchronous workflow is triggered to schedule automated email notifications leading up to the renewal date.
flowchart TD
Start([Subscription Created]) --> TriggerWorkflow[Trigger Upstash Workflow]
TriggerWorkflow --> CheckActive{Is Active?}
CheckActive -- Yes --> CalcDates[Calculate Reminder Dates <br> 10, 5, 2, and 0 days remaining]
CheckActive -- No / Cancelled --> End([End Workflow])
CalcDates --> Wait10[Wait until 10 days remaining]
Wait10 --> SendEmail10[Send 10-day Alert via Nodemailer]
SendEmail10 --> Wait5[Wait until 5 days remaining]
Wait5 --> SendEmail5[Send 5-day Alert via Nodemailer]
SendEmail5 --> Wait2[Wait until 2 days remaining]
Wait2 --> SendEmail2[Send 2-day Alert via Nodemailer]
Wait2 --> Wait0[Wait until Renewal Day]
Wait0 --> SendEmail0[Send Renewal Day Invoice/Alert via Nodemailer]
SendEmail0 --> AutoRenew{Is Auto-Renew True?}
AutoRenew -- Yes --> UpdateDates[Update Renewal Date] --> CalcDates
AutoRenew -- No --> End
- π Secure User Authentication: JWT-based signup, login, and token validation with password hashing via bcryptjs.
- π‘οΈ Arcjet Security Shield: Built-in rate limiting, bot protection, and protection against malicious requests.
- π Upstash Automated Workflows: Reliable execution loops for scheduling reminder tasks even if the server restarts.
- π§ Dynamic Email Templates: Beautifully designed HTML templates for renewal reminders.
- π Structured Architecture: Clear separation of concerns with models, routes, controllers, and middlewares.
- π§ͺ Flexible Database Modes: Automatically connects to your MongoDB Atlas cluster or provisions a local in-memory MongoDB database during development if needed.
βββ config/ # Configuration details (Arcjet, Env vars, Nodemailer, Upstash)
βββ controllers/ # Request handlers (Auth, User, Subscription, Workflow)
βββ database/ # Database connection configuration (MongoDB Atlas/Local)
βββ middlewares/ # Custom Express middlewares (Arcjet, Auth, Error handling)
βββ models/ # Mongoose schemas (User, Subscription)
βββ routes/ # Express endpoints definitions
βββ utils/ # Email helper functions and HTML layouts
βββ app.js # Application bootstrap and initialization
βββ package.json # Dependencies and scripts configuration
βββ README.md # Project documentation
| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
POST |
/api/v1/auth/sign-up |
Create a new user account | No |
POST |
/api/v1/auth/sign-in |
Authenticate and obtain JWT token | No |
POST |
/api/v1/auth/sign-out |
Clear user session cookies/tokens | Yes |
| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
GET |
/api/v1/users |
Fetch all user profiles | Yes |
GET |
/api/v1/users/:id |
Fetch specific user profile | Yes |
| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
POST |
/api/v1/subscriptions |
Create a new subscription | Yes |
GET |
/api/v1/subscriptions |
Get all active subscriptions for the user | Yes |
GET |
/api/v1/subscriptions/:id |
Get details of a specific subscription | Yes |
PUT |
/api/v1/subscriptions/:id |
Update subscription details | Yes |
DELETE |
/api/v1/subscriptions/:id |
Cancel/delete a subscription | Yes |
GET |
/api/v1/subscriptions/user/:id |
Fetch all subscriptions by a specific user ID | Yes |
| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
POST |
/api/v1/workflows/subscription/reminder |
Webhook triggered by Upstash Workflows | Upstash Only |
Follow these instructions to set up and run SubDub locally on your machine.
Ensure you have the following installed:
git clone https://github.com/Lalitmukesh69/subscription-tracker-api.git
cd subscription-tracker-apinpm installCreate a .env.development.local file in the root directory and populate it with your api keys and credentials:
# Server configuration
PORT=5500
SERVER_URL="http://localhost:5500"
NODE_ENV=development
# Database Configuration
DB_URI="mongodb+srv://<username>:<password>@cluster0.mongodb.net/subscriptionTracker"
# Authentication
JWT_SECRET="generate-a-long-random-string-here"
JWT_EXPIRES_IN="1d"
# Arcjet Protection
ARCJET_KEY="your-arcjet-api-key"
ARCJET_ENV="development"
# Upstash Workflows (QStash)
QSTASH_URL="http://127.0.0.1:8080" # local development or production QStash URL
QSTASH_TOKEN="your-qstash-token"
# Nodemailer Credentials
EMAIL_PASSWORD="your-email-app-password"npm run devnpm startDistributed under the MIT License. See LICENSE for more information.
Lalit Mukesh β @Lalitmukesh69