nodejs-backend

Node.js backend patterns: layered architecture, TypeScript, validation, error handling, security, deployment. Use when building REST APIs, Express/Fastify servers, or server-side TypeScript.

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "nodejs-backend" with this command: npx skills add iliaal/ai-skills/iliaal-ai-skills-nodejs-backend

Node.js Backend

Framework Selection

ContextChooseWhy
Edge/ServerlessHonoZero-dep, fastest cold starts
Performance APIFastify2-3x faster than Express, built-in schema validation
Enterprise/teamNestJSDI, decorators, structured conventions
Legacy/ecosystemExpressMost middleware, widest adoption

Ask user: deployment target, cold start needs, team experience, existing codebase.

Architecture

src/
├── routes/          # HTTP: parse request, call service, format response
├── middleware/       # Auth, validation, rate limiting, logging
├── services/        # Business logic (no HTTP types)
├── repositories/    # Data access only (queries, ORM)
├── config/          # Env, DB pool, constants
└── types/           # Shared TypeScript interfaces
  • Routes never contain business logic
  • Services never import Request/Response
  • Repositories never throw HTTP errors
  • For scripts/prototypes: single file is fine — ask "will this grow?"

TypeScript Rules

  • Use import type { } for type-only imports — eliminates runtime overhead
  • Prefer interface for object shapes (2-5x faster type resolution than intersections)
  • Prefer unknown over any — forces explicit narrowing
  • Use z.infer<typeof Schema> as single source of truth — never duplicate types and schemas
  • Minimize as assertions — use type guards instead
  • Add explicit return types to exported functions (faster declaration emit)
  • Untyped package? declare module 'pkg' { const v: unknown; export default v; } in types/ambient.d.ts

Validation

Zod (TypeScript inference) or TypeBox (Fastify native). Validate at boundaries only: request entry, before DB ops, env vars at startup. Use .extend(), .pick(), .omit(), .partial(), .merge() for DRY schemas.

Error Handling

Custom error hierarchy: AppError(message, statusCode, isOperational)ValidationError(400), NotFoundError(404), UnauthorizedError(401), ForbiddenError(403), ConflictError(409)

Centralized handler middleware:

  • AppError → return { error: message } with statusCode
  • Unknown → log full stack, return 500 + generic message in production
  • Async wrapper: const asyncHandler = (fn) => (req, res, next) => Promise.resolve(fn(req, res, next)).catch(next);

Codes: 400 bad input | 401 no auth | 403 no permission | 404 missing | 409 conflict | 422 business rule | 429 rate limited | 500 server fault

API Design

  • Resources: plural nouns (/users), max 2 nesting levels (/users/:id/orders)
  • Methods: GET read | POST create | PUT replace | PATCH partial | DELETE remove
  • Versioning: URL path /api/v1/
  • Response: { data, pagination?: { page, limit, total, totalPages } }
  • Errors: { error: { code, message, details? } }
  • Queries: ?page=1&limit=20&status=active&sort=createdAt,desc
  • Return Location header on 201. Use 204 for successful DELETE with no body.

Async Patterns

PatternUse When
async/awaitSequential operations
Promise.allParallel independent ops
Promise.allSettledParallel, some may fail
Promise.raceTimeout or first-wins

Never readFileSync / sync methods in production. Offload CPU work to worker threads (Piscina). Stream large payloads.

Production Resilience

  • Caching: Redis cache-aside for DB/API responses; in-memory LRU with TTL for hot paths. Always invalidate on writes.
  • Load shedding: @fastify/under-pressure (or equivalent) — monitor event loop delay, heap, RSS; return 503 when thresholds exceeded.
  • Response schemas: In Fastify, always define response schemas — enables fast-json-stringify for 2-3x faster serialization.

Discipline

  • For non-trivial changes, pause and ask: "is there a more elegant way?" Skip for obvious fixes.
  • Simplicity first — every change as simple as possible, impact minimal code
  • Only touch what's necessary — avoid introducing unrelated changes
  • No hacky workarounds — if a fix feels wrong, step back and implement the clean solution
  • Verify: tsc --noEmit && npm test pass with zero warnings before declaring done

References

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

pinescript

No summary provided by upstream source.

Repository SourceNeeds Review
General

react-frontend

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

code-review

No summary provided by upstream source.

Repository SourceNeeds Review