Skip to content

Node.js Do's and Don'ts

This lesson distills the best practices from this course into a fast, scannable list of do's and don'ts, useful as a quick refresher before shipping a Node.js feature or reviewing a pull request.

Do's and Don'ts by Category

Framing guidance as explicit do's and don'ts makes it easier to catch violations quickly during code review, rather than having to reconstruct the underlying reasoning from scratch every time.

Each pairing below corresponds to a lesson covered earlier in this course, if a "don't" feels unfamiliar, that lesson has the full explanation and examples.

// Don't
fs.readFileSync(path); // inside a request handler
exec(`convert ${userInput}`); // unsanitized shell command

// Do
await fs.promises.readFile(path);
spawn('convert', [userInput]); // arguments passed separately, no shell

Both "do" examples avoid blocking the event loop and avoid shell injection risk, the underlying theme behind most items on this list.

Quick Reference Format

DON'T: <risky or inefficient pattern>
DO:    <safer or more efficient alternative>
  • Each item pairs a common mistake with its safer or more efficient alternative.
  • Most items map directly back to a full lesson earlier in this course.
  • Use this list as a fast pre-ship or code-review checklist, not a replacement for understanding why.

Do's and Don'ts Cheatsheet

The most important pairings across async code, security, and structure.

Don't Do
Use fs.*Sync() inside request handlers Use fs.promises.* or callback-based async APIs
Concatenate user input into SQL queries Use parameterized queries (?/$1 placeholders)
Hash passwords with plain SHA-256 Use bcrypt/argon2 for password hashing
Store secrets in source code Use environment variables, never commit .env
Ignore the 'error' event on emitters/streams Always attach an 'error' listener
Return raw stack traces to API clients Log details server-side, return generic messages

Async Code

Async mistakes are some of the most common in Node.js code, since they often fail silently rather than with an obvious error.

  • Don't await independent async calls sequentially, use Promise.all() when they don't depend on each other.
  • Do wrap await calls in try/catch, especially inside Express route handlers.
  • Don't mix callbacks and promises inconsistently across the same codebase.
  • Do use for await...of for consuming Readable streams cleanly.

Security

Security mistakes are often invisible until they're exploited, making consistent habits especially valuable here.

  • Don't trust req.body/req.params/req.query without validating them.
  • Do apply helmet(), cors(), and rate limiting to every new Express app.
  • Don't compare secrets or signatures with ===, use crypto.timingSafeEqual().
  • Do rotate and never commit secrets like JWT_SECRET or database credentials.

Common Mistakes

  • Treating this list as a substitute for understanding the reasoning behind each item.
  • Applying these guidelines inconsistently across a codebase or team.
  • Skipping code review checks for items on this list because they seem "obvious".
  • Not updating this kind of checklist as new best practices emerge over time.

Key Takeaways

  • Do's and don'ts distill best practices into a fast, scannable reference.
  • Async, security, and error-handling mistakes are the most common categories worth double-checking.
  • Each item maps back to a fuller lesson elsewhere in this course for deeper context.
  • Use this list actively during code review, not just as background reading.

Pro Tip

Turn a list like this into an actual PR review checklist or linting rule where possible (ESLint has rules for several of these, like disallowing *Sync calls in certain files). Automating the check is more reliable than relying on memory during a busy review.