Skip to main content
This skill teaches Node.js decision-making principles for 2025, not fixed code patterns to copy. Learn to THINK about architecture and choose frameworks based on context.

What This Skill Provides

The Node.js Best Practices skill provides comprehensive Node.js development principles covering framework selection, async patterns, architecture, error handling, validation, and security.

Core Knowledge Areas

Framework Selection

Decision trees for Hono (edge), Fastify (performance), Express (stable), NestJS (enterprise)

Runtime Considerations

Node.js 22+ native TypeScript, ESM vs CommonJS, Bun vs Deno considerations

Async Patterns

Async/await, Promise.all, event loop awareness, I/O vs CPU-bound work

Architecture

Layered structure (Controller → Service → Repository), dependency injection

Error Handling

Centralized error handling, custom error classes, status code selection

Security

Input validation, parameterized queries, password hashing, JWT verification

When This Skill Is Loaded

Agents load this skill when:
  • Building Node.js applications or APIs
  • Choosing frameworks for backend projects
  • Implementing async patterns
  • Designing backend architecture
  • Handling errors and validation
  • Securing Node.js applications
  • Optimizing Node.js performance
  • Writing tests for Node.js code

Use Cases

Framework Selection (2025)

Decision tree based on context:
What are you building?

├── Edge/Serverless (Cloudflare, Vercel)
│   └── Hono (zero-dependency, ultra-fast cold starts)

├── High Performance API
│   └── Fastify (2-3x faster than Express)

├── Enterprise/Team familiarity
│   └── NestJS (structured, DI, decorators)

├── Legacy/Stable/Maximum ecosystem
│   └── Express (mature, most middleware)

└── Full-stack with frontend
    └── Next.js API Routes or tRPC
Always ASK the user about deployment target and requirements before choosing a framework. Don’t default to Express for edge deployments or Hono for enterprise projects.

Framework Comparison

FactorHonoFastifyExpress
Best forEdge, serverlessPerformanceLegacy, learning
Cold startFastestFastModerate
EcosystemGrowingGoodLargest
TypeScriptNativeExcellentGood
Learning curveLowMediumLow

Runtime Considerations (2025)

Node.js

Use for:
  • General purpose
  • Largest ecosystem
  • Native TS (22+)
  • Production stability

Bun

Use for:
  • Performance critical
  • Built-in bundler
  • Fast startup
  • Modern tooling

Deno

Use for:
  • Security-first
  • Built-in TypeScript
  • Web standards
  • Fresh projects

Async Patterns Decision

When to Use Each Pattern

  • async/await - Sequential async operations
  • Promise.all - Parallel independent operations
  • Promise.allSettled - Parallel where some can fail
  • Promise.race - Timeout or first response wins

Event Loop Awareness

I/O-bound (async helps):
├── Database queries
├── HTTP requests
├── File system
└── Network operations

CPU-bound (async doesn't help):
├── Crypto operations
├── Image processing
├── Complex calculations
└── → Use worker threads or offload

Key Principles

Layered Architecture

Request Flow:
  1. Controller/Route Layer - Handles HTTP specifics, input validation at boundary
  2. Service Layer - Business logic, framework-agnostic
  3. Repository Layer - Data access only, database queries
Why: Testability, flexibility, clarity

Error Handling Strategy

Client Gets

  • Appropriate HTTP status
  • Error code for handling
  • User-friendly message
  • NO internal details

Logs Get

  • Full stack trace
  • Request context
  • User ID (if applicable)
  • Timestamp

Status Code Selection

SituationStatusWhen
Bad input400Client sent invalid data
No auth401Missing/invalid credentials
No permission403Valid auth, not allowed
Not found404Resource doesn’t exist
Conflict409Duplicate or state conflict
Validation422Valid schema, business rules fail
Server error500Our fault, log everything

Validation Strategy

Validate at boundaries:
  • API entry point (request body/params)
  • Before database operations
  • External data (API responses, file uploads)
  • Environment variables (at startup)
Library Selection:
LibraryBest For
ZodTypeScript first, type inference
ValibotSmaller bundle, tree-shakeable
ArkTypePerformance critical
YupExisting React Form usage

API Patterns

API design principles for REST, GraphQL, tRPC

Python Patterns

Alternative backend runtime patterns

Rust Pro

High-performance systems programming

Which Agents Use This Skill

Backend Specialist

The Backend Specialist loads this skill for all Node.js development work. It’s used alongside api-patterns for API design and other runtime skills as needed.
The Backend Specialist combines this with api-patterns, database-design, and security skills for comprehensive backend development.

Security Checklist

Critical Security Measures:
  • Input validation - All inputs validated
  • Parameterized queries - No SQL string concatenation
  • Password hashing - bcrypt or argon2
  • JWT verification - Always verify signature and expiry
  • Rate limiting - Protect from abuse
  • Security headers - Helmet.js or equivalent
  • HTTPS - Everywhere in production
  • CORS - Properly configured
  • Secrets - Environment variables only
  • Dependencies - Regularly audited

Security Mindset

Trust nothing:
├── Query params → validate
├── Request body → validate
├── Headers → verify
├── Cookies → validate
├── File uploads → scan
└── External APIs → validate response

Testing Strategy

TypePurposeTools
UnitBusiness logicnode:test, Vitest
IntegrationAPI endpointsSupertest
E2EFull flowsPlaywright

Built-in Test Runner

Node.js 22+ includes native test runner:
node --test src/**/*.test.ts
No external dependency needed, includes coverage reporting and watch mode.

Anti-Patterns to Avoid

Don’t:
  • Use Express for new edge projects (use Hono)
  • Use sync methods in production code (fs.readFileSync)
  • Put business logic in controllers
  • Skip input validation
  • Hardcode secrets
  • Trust external data without validation
  • Block event loop with CPU work
  • Use any type in TypeScript
Do:
  • Choose framework based on context
  • Ask user for preferences when unclear
  • Use layered architecture for growing projects
  • Validate all inputs at boundaries
  • Use environment variables for secrets
  • Profile before optimizing
  • Use TypeScript strict mode

Decision Checklist

Before implementing:
  • Asked user about stack preference?
  • Chosen framework for THIS context? (not just default)
  • Considered deployment target? (edge/serverless/container)
  • Planned error handling strategy?
  • Identified validation points?
  • Considered security requirements?
  • Chosen testing approach?

Module System Decision

ESM (import/export)

Use for:
  • Modern standard
  • Better tree-shaking
  • Async module loading
  • New projects

CommonJS (require)

Use for:
  • Legacy compatibility
  • Existing codebases
  • Some edge cases

Remember: Node.js best practices are about decision-making, not memorizing patterns. Every project deserves fresh consideration based on its requirements, deployment target, and constraints.

Build docs developers (and LLMs) love