Nodejs Best Practices
Principles and decision-making for Node.js development in 2025.
Content
> Principles and decision-making for Node.js development in 2025.
> Learn to THINK, not memorize code patterns.
When to Use
Use this skill when making Node.js architecture decisions, choosing frameworks, designing async patterns, or applying security and deployment best practices.
---
⚠️ How to Use This Skill
This skill teaches decision-making principles, not fixed code to copy.
- -ASK user for preferences when unclear
- -Choose framework/pattern based on CONTEXT
- -Don't default to same solution every time
---
1. Framework Selection (2025)
Decision Tree
Comparison Principles
| Factor | Hono | Fastify | Express |
|---|---|---|---|
| **Best for** | Edge, serverless | Performance | Legacy, learning |
| **Cold start** | Fastest | Fast | Moderate |
| **Ecosystem** | Growing | Good | Largest |
| **TypeScript** | Native | Excellent | Good |
| **Learning curve** | Low | Medium | Low |
Selection Questions to Ask:
1. What's the deployment target?
2. Is cold start time critical?
3. Does team have existing experience?
4. Is there legacy code to maintain?
---
2. Runtime Considerations (2025)
Native TypeScript
Module System Decision
Runtime Selection
| Runtime | Best For |
|---|---|
| **Node.js** | General purpose, largest ecosystem |
| **Bun** | Performance, built-in bundler |
| **Deno** | Security-first, built-in TypeScript |
---
3. Architecture Principles
Layered Structure Concept
Why This Matters:
- -Testability: Mock layers independently
- -Flexibility: Swap database without touching business logic
- -Clarity: Each layer has single responsibility
When to Simplify:
- -Small scripts → Single file OK
- -Prototypes → Less structure acceptable
- -Always ask: "Will this grow?"
---
4. Error Handling Principles
Centralized Error Handling
Error Response Philosophy
Status Code Selection
| Situation | Status | When |
|---|---|---|
| Bad input | 400 | Client sent invalid data |
| No auth | 401 | Missing or invalid credentials |
| No permission | 403 | Valid auth, but not allowed |
| Not found | 404 | Resource doesn't exist |
| Conflict | 409 | Duplicate or state conflict |
| Validation | 422 | Schema valid but business rules fail |
| Server error | 500 | Our fault, log everything |
---
5. Async Patterns Principles
When to Use Each
| Pattern | Use When |
|---|---|
| `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
Avoiding Event Loop Blocking
- -Never use sync methods in production (fs.readFileSync, etc.)
- -Offload CPU-intensive work
- -Use streaming for large data
---
6. Validation Principles
Validate at Boundaries
Validation Library Selection
| Library | Best For |
|---|---|
| **Zod** | TypeScript first, inference |
| **Valibot** | Smaller bundle (tree-shakeable) |
| **ArkType** | Performance critical |
| **Yup** | Existing React Form usage |
Validation Philosophy
- -Fail fast: Validate early
- -Be specific: Clear error messages
- -Don't trust: Even "internal" data
---
7. Security Principles
Security Checklist (Not Code)
- -[ ] Input validation: All inputs validated
- -[ ] Parameterized queries: No string concatenation for SQL
- -[ ] 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
---
8. Testing Principles
Test Strategy Selection
| Type | Purpose | Tools |
|---|---|---|
| **Unit** | Business logic | node:test, Vitest |
| **Integration** | API endpoints | Supertest |
| **E2E** | Full flows | Playwright |
What to Test (Priorities)
1. Critical paths: Auth, payments, core business
2. Edge cases: Empty inputs, boundaries
3. Error handling: What happens when things fail?
4. Not worth testing: Framework code, trivial getters
Built-in Test Runner (Node.js 22+)
---
10. Anti-Patterns to Avoid
❌ DON'T:
- -Use Express for new edge projects (use Hono)
- -Use sync methods in production code
- -Put business logic in controllers
- -Skip input validation
- -Hardcode secrets
- -Trust external data without validation
- -Block event loop with CPU work
✅ DO:
- -Choose framework based on context
- -Ask user for preferences when unclear
- -Use layered architecture for growing projects
- -Validate all inputs
- -Use environment variables for secrets
- -Profile before optimizing
---
11. Decision Checklist
Before implementing:
- -[ ] Asked user about stack preference?
- -[ ] Chosen framework for THIS context? (not just default)
- -[ ] Considered deployment target?
- -[ ] Planned error handling strategy?
- -[ ] Identified validation points?
- -[ ] Considered security requirements?
---
> Remember: Node.js best practices are about decision-making, not memorizing patterns. Every project deserves fresh consideration based on its requirements.
FAQ
Discussion
Loading comments...