Backend Module Map
Every backend building block, what it owns, and where the money code lives.
Last updated Thu Jul 16 2026 00:00:00 GMT+0000 (Coordinated Universal Time)
TL;DR -The backend is split into focused modules, each responsible for one slice of the product (auth, chat, live rooms, the wallet, and so on). The wallet module is the financial heart and gets extra care.
Who this is for -Product & Business: skim "What a module is" and the inventory table to see the shape of the product. Engineering & Backend: the full table, the cross-cutting pieces, and the wallet deep-dive.
What a module is
The backend is built with NestJS, a framework that encourages you to organize code into modules -self-contained bundles that each own one area of the app. One module handles logging in, another handles chat, another handles live rooms, and so on. Grouping code this way keeps each concern isolated and easy to reason about.
Each module owns three kinds of code: controllers (the entry points that
receive requests), services (the logic that does the work), and DTOs
(the definitions of what a valid request looks like). Anything shared across
modules -the database connection, login checks, security settings -lives
in a common area (backend/src/common/).
The backend lives in backend/src/modules/.
Module inventory
Here's the full list of modules and what each one is responsible for. The right column lists the main API endpoints (the URLs the app calls) or gateways (the live channels) each module exposes.
| Module | Owns | Key endpoints / gateways |
|---|---|---|
auth | OTP login/signup (phone + email), token refresh, devices, email change | POST /auth/otp/request, POST /auth/otp/verify, POST /auth/refresh, POST /auth/logout |
users | Profiles, avatars, usernames, presence | GET/PATCH /users/me, GET /users/:id, avatar upload |
follow-requests / blocking | Social graph: follows, friend requests, blocks | /follows/*, /friend-requests/*, /blocks/* |
chat | Conversations, messages, typing | REST + ChatGateway (Socket.IO) |
calls | 1:1 call sessions | /calls/* |
live | Live rooms, participants, stage, PK battles, media sessions | /live/* + LiveGateway + LiveMediaService (mediasoup) |
gifts | Gift catalog | GET /gifts |
wallet | Coins, diamonds, purchases, gifting spend, IAP verification, refunds | /wallet/* -see the economy |
withdrawals | Creator cash-out requests | POST /withdrawals, admin review endpoints |
vip | VIP subscription tiers | /vip/* |
discovery / search / suggestions | Room and user discovery feeds | /discovery/*, /search/* |
notifications | In-app notification feed | /notifications/* |
safety | User reports | POST /reports |
settings | App-level settings | /settings/* |
admin | Everything the admin portal consumes | /admin/* (dashboard stats, users, reports, withdrawals, live rooms) |
Cross-cutting pieces (backend/src/common/)
Some concerns aren't owned by any single module because every module needs
them -the database connection, the login check on protected endpoints, and
the guardrail that rejects malformed requests. These shared pieces live in
backend/src/common/.
prisma/prisma.service.ts-the singleton Prisma client, injected everywhere; also hosts$transactionhelpers. (Prisma is the tool the backend uses to talk to the PostgreSQL database.)auth/jwt-auth.guard.ts-bearer-token guard used by every authenticated controller; decorates requests withAuthenticatedUser(userId,role). In plain terms: it checks the caller's login token before the request is allowed through.- Global
ValidationPipe(inmain.ts) -whitelist: true,forbidNonWhitelisted: true,transform: true. Every request body must match its DTO exactly. Webhook endpoints that accept third-party payload shapes (Pub/Sub, Apple notifications) take untyped bodies deliberately so the pipe skips them, then parse defensively by hand.
Wallet module in detail
The wallet module is where all the money lives, so it deserves a closer look. It handles buying coins, spending them on gifts, converting earnings, paying out creators, and processing refunds -and it double-checks every purchase with Apple or Google before crediting anyone. Here's how its responsibilities are split across files:
| File | Responsibility |
|---|---|
wallet.service.ts | All balance movements: purchase, gift spend, conversion, settlement, refunds |
apple-iap.service.ts | Verifies StoreKit transactions against Apple's App Store Server API |
google-iap.service.ts | Verifies Play purchase tokens, lists voided purchases, authenticates RTDN pushes |
voided-purchase-sweep.service.ts | Periodic refund reconciliation sweep (RTDN backstop) |
economy.constants.ts | Every rate, package, and fee in one place -the single source of economic truth |
wallet.module.ts | Controllers, including the store-refund webhook endpoints |
Every service has a matching .spec.ts test file. The wallet test suite is
deliberately thorough because the cost of a money bug is high; it covers
purchase idempotency (a receipt can't be counted twice), cross-account
replay rejection (a receipt from one account can't credit another),
store-fee modeling, gift spend rules, settlement, and refund clawback.
Related pages
- System Architecture -how the backend fits with everything else.
- Data Model -the database tables these modules read and write.
- The economy -the money rules the wallet enforces.