AI-consumed reference. Optimized for Claude to read during execution. Human-readable explanation: see docs/architecture/HIERARCHICAL_PLANNING.md or docs/getting-started/ depending on topic.
Node.js Expert — Gotchas & Decisions
Use Context7 for Express/NestJS/Fastify docs.
Key Decisions
decisions[4]{choice,use_when}:
Express vs NestJS vs Fastify,"Express: simple APIs. NestJS: enterprise/DI/decorators. Fastify: high perf"
Prisma vs TypeORM vs Drizzle,"Prisma: best DX/types. TypeORM: Active Record pattern. Drizzle: SQL-like + lightweight"
Zod vs Joi vs class-validator,"Zod: TS-first inference. Joi: runtime schemas. class-validator: NestJS decorators"
JWT vs session,"JWT: stateless/microservices. Session: monolith/server-rendered"
Gotchas
forEach+async: does NOT await. Usefor...oforPromise.all(items.map(async ...))- Express error handler: MUST have 4 params
(err, req, res, next)— even if unused, or Express ignores it - Unhandled promise rejection crashes Node 15+ — always catch or use
process.on('unhandledRejection') asyncHandlerwrapper: wrap Express route handlers to catch async errors →next(err)req.bodyisundefinedwithoutexpress.json()middleware — common setup missprocess.env.PORTis string — parse withparseInt()orNumber()before comparison- NestJS:
@Injectable()with@Module({ providers: [...] })— forgetting module registration = runtime error - Stream backpressure: always handle
drainevent on writable streams for large data __dirnamenot available in ESM — useimport.meta.dirname(Node 21+) orfileURLToPath(import.meta.url)