1---2name: node-backend3description: Use for Node.js backend services — NestJS, Fastify, Express — API design, middleware, auth, database integration, testing. Triggers — Node/TS server code, package.json, 'nestjs'.4---56# Node.js Backend Development78## When to use9- Writing REST or GraphQL APIs with Express, Fastify, or NestJS10- Designing middleware, guards, interceptors, or pipes11- Implementing authentication, authorization, or rate-limiting12- Integrating ORMs (Prisma, TypeORM, Drizzle) or raw query builders13- Writing unit/integration tests with Jest or Vitest14- Profiling performance or fixing memory leaks in a Node.js process1516## Workflow17181. **Classify** — REST, GraphQL, gRPC, WebSocket, or worker/queue service.192. **Choose the framework tier**:20 - NestJS: structured enterprise services (DI, modules, decorators, CLI scaffolding).21 - Fastify: high-throughput APIs where raw RPS matters; schema-first with JSON Schema.22 - Express: simple services or legacy projects; minimal overhead.233. **Scaffold the project** using the framework CLI:24 - NestJS: `nest new my-service --strict`25 - Fastify: `npm create fastify`26 - Express: plain `npm init` + `express`, `helmet`, `pino` minimal setup274. **Design the module/layer boundary**:28 - NestJS: `Module → Controller → Service → Repository`29 - Fastify/Express: `routes → handlers → services → data-access`305. **Define data contracts first** — TypeScript interfaces or Zod/class-validator schemas before any handler code.316. **Implement handlers** — keep controllers thin (parse, delegate, respond). Business logic lives in services.327. **Authenticate and authorize** before any business logic:33 - JWTs: validate signature + expiry; never decode without `verify`.34 - API keys: constant-time comparison with `crypto.timingSafeEqual`.358. **Add error handling globally** — NestJS: `ExceptionFilter`; Fastify: `setErrorHandler`; Express: 4-arg error middleware at the end.369. **Write tests**: unit tests for services (mock dependencies), integration tests hitting the real DB via test containers.3710. **Harden**: helmet, cors (explicit allowlist), rate-limit, request size cap, SQL injection prevention via parameterised queries.3811. **Audit** against .claude/checklists/security.md and .claude/checklists/performance.md before deploying.3940## Standards4142### TypeScript43- Enable `strict: true`, `noImplicitAny`, `strictNullChecks` in `tsconfig.json`.44- Use `zod` or `class-validator` for runtime validation of all external input.45- Avoid `any`; use `unknown` and narrow explicitly.4647### NestJS specifics48- One feature per module; no circular module imports — use forwardRef only as last resort.49- Providers are singletons by default; use `REQUEST` scope only when truly request-scoped.50- Use `@UseGuards`, `@UsePipes`, `@UseInterceptors` at the controller/handler level, not ad-hoc in services.51- Config: `@nestjs/config` with a typed `ConfigService`; never `process.env.X` inline.5253### Fastify specifics54- Register all plugins with `fastify-plugin` wrapper to share decorations across encapsulation.55- Define JSON Schema for every route's `body`, `querystring`, `params`, `response` — this enables auto-validation and serialisation optimisation.56- Use Fastify's `pino` logger (already included); do not add Winston on top.5758### Database59- Use connection pooling (pg-pool, Prisma connection limit, TypeORM pool config) — never create a new connection per request.60- All mutations must be in transactions for multi-step writes.61- Parameterise every query — never string-interpolate user input into SQL.62- Run migrations in CI before integration tests; never auto-migrate in production startup.6364### Error model65- Return RFC 7807 Problem+JSON (`type`, `title`, `status`, `detail`, `instance`).66- 4xx for client errors, 5xx for server faults; never return a stack trace to clients.67- Log correlation IDs with every error; propagate `X-Request-ID` through service calls.6869### Do not70- Do not use `require()` for dynamic plugin loading at request time — startup-time only.71- Do not store secrets in environment-unguarded constants; use `.env` + validation at startup.72- Do not swallow errors with empty `catch {}` blocks.73- Do not use synchronous `fs`, `crypto.randomBytes` (sync), or any blocking call in an async route handler.7475## Common mistakes to avoid7677| Mistake | Fix |78|---|---|79| JWT secret hardcoded in code | Load from `process.env`; validate its presence at startup. |80| Unhandled promise rejections crashing the process | Attach `process.on('unhandledRejection', ...)` and handle in async middleware. |81| Missing `await` on async middleware | `next()` fires before the async work finishes; always `await` or return the promise. |82| N+1 queries from ORMs | Use `include`/`join` or `DataLoader` pattern for batching. |83| Returning 200 on validation failure | Return 400 with structured error body; never 200 for errors. |84| Listening on port before DB is ready | Health-check the DB in startup; delay `listen()` or crash fast. |8586## Output format8788- New service: directory tree showing `module / controller / service / dto / entity` files.89- Route handler: TypeScript with typed request/response, validation pipe/schema, and error handling.90- Test file: Jest/Vitest describe block with happy path, validation failure, and auth failure cases.91- Config changes: diff of `tsconfig.json`, `package.json` scripts, environment variable list.9293## Related checklists94- .claude/checklists/security.md95- .claude/checklists/performance.md96- .claude/checklists/qa.md9798## Related agents99- .claude/agents/core/orchestrator.md100- .claude/agents/engineering/devops-engineer.md