A scalable, production-ready backend for Ubuy - a real-time auction platform.
- Overview
- Tech Stack
- Architecture
- Features
- Getting Started
- Environment Variables
- Developer Commands
- API Documentation
- Testing
- Coverage Reports
- Smoke Testing
- API Quick Check
- WebSocket Events
Real-time auction system with live bidding, user management, queue-based auction ending, and health monitoring.
- Node.js, NestJS, TypeScript
- MongoDB
- Socket.IO
- Redis (ioredis + Socket.IO Redis adapter)
- BullMQ (auction lifecycle jobs)
flowchart TB
subgraph Client["Client Applications"]
WEB[Web UI]
MOB[Mobile UI]
end
subgraph API["NestJS Backend"]
AUTH[Auth Module]
AUC[Auctions Module]
BID[Bids Module]
PAY[Payments Module]
NOTIF[Notifications Module]
UPLOAD[Uploads Module]
WS[Socket Gateway]
Q[Queue Workers BullMQ]
end
subgraph Data["Data and Infra"]
MDB[(MongoDB)]
REDIS[(Redis)]
end
subgraph External["External Services"]
CASHFREE[Cashfree]
CLOUDINARY[Cloudinary]
EMAIL[Email Provider]
end
WEB --> AUTH
WEB --> AUC
WEB --> BID
WEB --> PAY
WEB --> NOTIF
WEB --> UPLOAD
MOB --> AUTH
MOB --> AUC
MOB --> BID
MOB --> PAY
MOB --> NOTIF
BID --> WS
WS --> REDIS
AUTH --> MDB
AUC --> MDB
BID --> MDB
PAY --> MDB
NOTIF --> MDB
Q --> REDIS
Q --> MDB
PAY --> CASHFREE
UPLOAD --> CLOUDINARY
AUTH --> EMAIL
sequenceDiagram
autonumber
participant U as User
participant UI as Client UI
participant API as Auctions Controller
participant B as Bids Service
participant DB as MongoDB
participant R as Redis Adapter
participant WS as WebSocket Gateway
U->>UI: Enter bid amount
UI->>API: POST /v1/auctions/{id}/bids
API->>B: validate user and bid amount
B->>DB: read auction and current highest bid
B->>DB: write new bid and update auction
DB-->>B: updated auction state
B->>WS: publish bid update event
WS->>R: fan-out across instances
WS-->>UI: newBid event
UI-->>U: Show latest bid and leaderboard
sequenceDiagram
autonumber
participant Q as BullMQ Worker
participant A as Auctions Service
participant DB as MongoDB
participant N as Notifications
participant P as Payments Service
participant CF as Cashfree
Q->>A: Process auction end job
A->>DB: Mark auction ended and resolve winner
A->>N: Notify winner and seller
A->>P: Create payment link for winner
P->>CF: Request payment link
CF-->>P: linkId and payment URL
P->>DB: Store payment metadata and expiry
P->>N: Send payment pending notification
sequenceDiagram
autonumber
participant U as User
participant API as Auth Controller
participant S as Auth Service
participant DB as MongoDB
participant E as Email Provider
U->>API: POST /v1/auth/signup
API->>S: validate payload
S->>DB: create user (unverified)
S->>E: send verification code
E-->>U: verification email
U->>API: POST /v1/auth/verify-email
API->>S: verify code
S->>DB: mark email as verified
U->>API: POST /v1/auth/login
API->>S: verify credentials
S-->>U: JWT access token
U->>API: GET /v1/auth/me with Bearer token
API-->>U: profile payload
- JWT Authentication
- Role-based authorization
- Real-time bidding
- Auction lifecycle management
- Health checkpoint endpoint for backend, MongoDB, Redis, config, and memory
- Implemented modules: Auth, Users, Auctions, Bids, Queue, Health
- Root endpoint (
GET /) returns runtime service status - Health endpoint (
GET /health) returns dependency checks and readiness
- Modular Monolith -> Easily convertible to microservices
- WebSockets -> Real-time bidding updates
- Redis -> Caching + scaling sockets
- Kafka (Future) -> Event-driven architecture
- Stateless backend
- Horizontal scaling
- Redis adapter for WebSockets
src/
|-- common/
|-- modules/
|-- config/
|-- database/
`-- main.ts
- Node.js 20+
- npm 10+
- MongoDB instance
- Redis instance
git clone https://github.com/Anujsinghdevx/Ubuy-backend.git
cd ubuy-backend
npm install
npm run start:devBy default, the application starts on port 8080 unless PORT is set.
For the full local demo flow, run:
npm run demo:startThen open:
curl http://localhost:8080/
curl http://localhost:8080/healthFor local development and deployment, set at least:
MONGO_URIREDIS_URLfor Render Redis or another hosted Redis instanceJWT_SECRETPAYMENT_WEBHOOK_SECRETfor validating incoming payment webhooksPORTis provided by Render in production, but can default locallyENABLE_ADMIN_TOOLS=trueonly when you want Swagger and the BullMQ dashboard exposed in productionFRONTEND_BASE_URLoptional, used to auto-build payment return URL fallbackPAYMENT_RETURN_URLoptional, explicit fallback redirect URL after paymentPAYMENT_NOTIFY_URLoptional, explicit fallback webhook notify URL sent to payment provider
For secret rotation freshness automation in CI, set repository variables:
JWT_SECRET_ROTATED_ATinYYYY-MM-DDformatPAYMENT_WEBHOOK_SECRET_ROTATED_ATinYYYY-MM-DDformat
| Command | Purpose |
|---|---|
npm run start:dev |
Run API in watch mode |
npm run demo:start |
Start local infra, seed demo data, and run the app |
npm run build |
Compile NestJS app |
npm run lint |
Run ESLint with autofix |
npm run check:local |
Build + prettier check + unit + integration |
npm run test:unit |
Run unit tests |
npm run test:integration |
Run integration tests |
npm run test:e2e |
Run e2e tests |
npm run test:smoke |
Run smoke tests |
npm run test:all:cov |
Generate combined coverage |
npm run infra:local:up |
Start local MongoDB + Redis via Docker |
npm run infra:local:down |
Stop local MongoDB + Redis |
npm run start:dev:loadtest |
Run backend with .env.loadtest.local |
npm run load:test |
Run baseline local load test (health + auctions) |
npm run load:test:1k |
Run 1000-user ramp local load test |
npm run security:audit |
Run npm audit at high severity threshold |
- Swagger UI:
/docs - OpenAPI JSON:
/docs-json - BullMQ dashboard:
/admin/queues
Notes:
- Swagger and BullMQ dashboard are available outside production by default.
- In production, expose them only when
ENABLE_ADMIN_TOOLS=true.
For the complete testing strategy, commands, standards, CI recommendations, and troubleshooting, see:
Run the suite-specific commands if you want separate reports for each test layer:
- Unit:
npm run test:unit:cov - Integration:
npm run test:integration:cov - E2E:
npm run test:e2e:cov - Smoke:
npm run test:smoke:cov - Combined:
npm run test:all:cov
Each command writes its report to a separate folder:
- coverage/unit/lcov-report/index.html
- coverage/integration/lcov-report/index.html
- coverage/e2e/lcov-report/index.html
- coverage/smoke/lcov-report/index.html
- coverage/combined/lcov-report/index.html
To view a report locally, open the matching index.html file in your browser or in VS Code. In GitHub Actions, download the uploaded artifact with the matching name and open the same file inside the artifact.
- Full smoke suite:
npm run test:smoke- GitHub Actions options:
.github/workflows/smoke-tests.yml
Manual-only workflow (run from Actions tab), supports choosing core or full suite.
Uses external secrets (MONGO_URI, REDIS_URL, JWT_SECRET) from repository secrets.
.github/workflows/smoke-tests-services.yml
Runs on push commits and manual dispatch, supports choosing core or full suite. Uses GitHub Actions service containers (MongoDB + Redis) and does not require external runtime secrets.
GET /-> service runtime statusGET /health-> backend, MongoDB, Redis, config, memory checksPOST /v1/auth/signupPOST /v1/auth/loginPOST /v1/auth/verify-emailGET /v1/auth/me(JWT required)POST /v1/auctions(JWT required)GET /v1/auctionsGET /v1/auctions/activeGET /v1/auctions/:id
- joinAuction
- leaveAuction
- placeBid
- newBid
- auctionEnded
Anuj Singh
Give a star if you like this project!