
BGV Employee Background Verification Platform
Hardening & scaling a multi-tenant background-verification platform
Sole engineer on a production BGV SaaS — architecture, API, web client, database and deployment.
Overview
I am the only engineer on a multi-tenant background-verification (BGV) SaaS platform used by an India-based verification-services company. It manages the full lifecycle of employee and business background checks — corporate clients onboard people to be vetted, 14 verification types run per subject, field work is farmed out to external vendors and law firms, and results roll up into a colour-coded case outcome with downloadable reports.
I designed the architecture, wrote the NestJS API and the Angular SPA, own the database and the deployment, and handle every ticket end to end. The codebase is roughly 105,000 hand-written lines across the two repositories and has been in continuous production use for several years.
Role
Sole full-stack developer
Backend
NestJS · TypeScript · MySQL / TypeORM · Redis / Bull
Frontend
Angular · NgRx · RxJS · Bootstrap
Infra
AWS S3 · Lambda / API Gateway · Docker
Client
An India-based background-verification services company
Executive Summary
The platform is a mature, multi-tenant B2B application that manages the full lifecycle of employee and business background checks: corporate clients onboard people (or companies) to be vetted, 14 different verification types are run per subject, field work is farmed out to external vendors and law firms, and results roll up into a colour-coded case outcome with downloadable reports.
It has been in continuous production use for several years and, from database snapshots, currently serves roughly 40 corporate clients, ~3,600 user accounts, and ~3,600 candidate cases, backed by 12,000+ uploaded verification documents.
I am its only engineer. I designed the architecture, wrote the backend and the frontend, own the database and the deployment, and handle every ticket end to end — from reproducing a client's prose bug report, through the fix, to sign-off on scope.
The Actors
| Role | Who they are | What they see |
|---|---|---|
| Super Admin / Admin | The BGV company's leadership and system operators | Everything |
| Employee | Internal staff — verification analysts and client relationship managers | historically: everything; now: only their assigned clients |
| Client | A corporate customer's primary login | Only their own organisation's candidates and cases |
| Client Sub-User | Additional logins under a client account | Their parent client's data |
| Vendor | External field-verification agencies and law firms | Only the specific verification jobs assigned to them |
| Candidate | An individual undergoing verification | Only their own record — a self-service portal to submit their details |
Lifecycle of 14 verification types
Each check is its own self-contained module — entity, controller, service, export service, repository, mappers, DTOs — generated from one blueprint:
| Category | Checks |
|---|---|
| Identity | Aadhaar, PAN, Passport, Driving Licence, Voter ID |
| History | Education, Employment, Address (electronic / offline / physical, with photo and video evidence) |
| Records | e-Court / court records, Police verification (routed through partner law firms), Global Database (international watchlist / sanctions screening) |
| Other | CIBIL (credit), Drug Panel (blood / hair / urine), Reference checks (professional and personal referees) |
Reporting
- MIS spreadsheets — Excel workbooks (one per verification type, plus a candidate-level roll-up) clients use to track a batch of cases and their statuses. Built with a spreadsheet library, streamed as downloads.
- Per-candidate PDF report — the formal deliverable, compiled from templates and rendered to PDF with headless Chrome, with per-section partials for each verification type.
System architecture
Backend — a disciplined modular monolith
Every feature is a NestJS module with the same internal layering: Controller → Service → Repository (a custom class per aggregate) → MySQL, with dedicated Mapper classes translating between DTOs and entities. Side effects — email, notifications, heavy row processing — leave the request path through an event bus and six Redis-backed Bull queues, each with a processor that logs queue lifecycle events and marks failures.
18
feature modules
~39
controllers
~82
services
~68
TypeORM entities
~241
HTTP routes
6 / 6
queues / processors
Frontend — Angular + NgRx at scale
RBAC is enforced in three independent layers, mirroring the backend authorization model.
Layer 1
Self-hosted identity platform
AuthGuard
PermissionGuard
ProfileGuard
Layer 2
Structural directive
*hasPermissions
in ~44 templates
hides buttons, cols, tabs
Layer 3
Navigation
Two role-specific
sidebar menus, each
item filtered by slug
~190
components
~130
routed screens
~32
NgRx feature stores
~40
lazy-loaded chunks
~16
FormArray dynamic forms
171
catchError blocks → 1 toast action
Technology stack
Backend
| Area | Choices |
|---|---|
| Area Choices Framework / language | NestJS 9, TypeScript |
| Database | MySQL 8, TypeORM 0.3.x (repository pattern, custom repository classes, mapper layer) |
| Queue / cache | Redis, Bull (6 queues) |
| Auth | Passport, JWT (header or cookie transport), bcrypt (12 rounds), separate short-lived reset-password strategy |
| Async | @nestjs/event-emitter event bus → listeners → queues |
| Transactional email HTTP API (primary) with SMTP fallback; Handlebars templates | |
| Files | AWS S3 + local disk; Multer uploads |
| Documents | Headless Chrome for PDF; ExcelJS + SheetJS for spreadsheets; JSZip for bulk download |
| Ops | Helmet, throttler, Terminus health check, structured logging (Winston / Pino), a CLI entrypoint for admin account creation |
| Deploy | Docker (multi-stage) or AWS Lambda + API Gateway via serverless-express |
| Validation | class-validator / class-transformer, global validation pipe with whitelisting |
Frontend
| Area | Choices |
|---|---|
| Framework / language | Angular, TypeScript |
| State | NgRx — store, effects, entity, router-store, devtools (~32 feature stores) |
| Reactive | RxJS |
| UI | Bootstrap 5 + ng-bootstrap; ApexCharts for dashboards; a multi-step wizard library for the candidate portal |
| Forms | Reactive Forms throughout; 16 FormArray-based dynamic forms; 10 custom validators (PAN, Aadhaar, GST, TAN, file-type, …) |
| Data | Client-side XLSX export on several list screens; blob downloads for server-generated reports |
| i18n | AWS S3 + local disk; Multer uploads |
| Documents | @ngx-translate (wired; English is the shipped locale) |
| Build / deploy | Angular CLI, environment file replacement (dev / UAT / prod), static SPA deployed to S3 |
What this demonstrates
- Backend engineering — an 18-module NestJS monolith with consistent layering, an event-driven side-effect architecture, six queue processors, and a deliberately-tuned posture for heavy synchronous work.
- Frontend engineering — a ~130-screen Angular SPA with ~32 NgRx feature stores, disciplined effect patterns, three-layer RBAC, and genuinely complex nested dynamic forms.
- Database — owning a ~68-entity MySQL schema; writing migrations with backfill and rollback; recognising and reporting schema drift.
- Security — finding and closing a cross-tenant data-exposure gap; finding unauthenticated admin APIs; reporting committed-secret exposure with a remediation plan.
- Debugging — root-causing a 100%-failure bulk pipeline through live reproduction and SQL inspection; a cross-domain date/timezone bug; a latent async race; a latent crash.
- DevOps — Docker and serverless deployment paths, S3 static hosting, environment management.
- Judgement — separating the ticket from the system state, fixing at the right layer, agreeing scope in writing, and reporting honest negative findings.

