DevAcademy
LearnNode.jsNode.js Best Practices
AdvancedNode.js

Node.js Best Practices

A checklist of habits for building reliable, secure, and maintainable Node.js applications.

Reading Time

12 min

Lesson

Lesson 34 of 34

Structure & Code Quality

  • Separate app.js (routes/middleware) from server.js (the actual .listen() call) for testability
  • Group routes by resource using express.Router()
  • Use async/await with a consistent error-handling pattern (a wrapper or try/catch + next(err))
  • Validate input at the boundary — reject bad requests before they reach business logic

Security

  • Never commit secrets — use environment variables and .gitignore .env
  • Hash passwords with bcrypt or argon2, never store them in plain text
  • Use parameterized queries for SQL; never concatenate user input into a query
  • Enable helmet() and a properly scoped CORS policy
  • Validate and limit file upload size and type

Graceful Shutdown

Try it yourself — edit and run

Console Output

Click “Run” to see the console output here.

Reliability

PracticeWhy
Centralize error handlingConsistent responses, easier debugging, no duplicated logic
Log structured errors, not just console.logMachine-readable logs are searchable in production
Handle graceful shutdownFinish in-flight requests before a container is killed
Set request timeoutsA hung upstream dependency shouldn't hang your whole server

Don't Ignore Unhandled Rejections

An unhandled promise rejection can silently fail or, in newer Node.js versions, crash the process entirely. Always add a process.on('unhandledRejection', ...) handler during development to catch bugs where a Promise's error was never caught.

Best Practice

Treat this checklist as a starting point, not a final answer — the right Node.js practices depend heavily on your app's scale and requirements. What matters most is being deliberate about these decisions rather than accepting whatever a tutorial's defaults happened to be.

Interview Questions

Quick Quiz

1. Why separate app.js from server.js?

2. Why handle SIGTERM in a production server?

3. What can happen if an unhandled promise rejection is ignored?

Previous