Skip to content
Knowledge Hub

Common mistakes in Node.js, NestJS and PostgreSQL backend code Intermediate

Most production bugs don’t come from hard algorithms. They come from a few dozen mistakes that repeat over and over: a forgotten await, money as floats, a transaction running on the wrong connection, fetch without a timeout.

This cluster gathers those mistakes into a catalog. Each one is a BAD/GOOD pair with a “Why”: what breaks, when it blows up, and why. All behavior was tested on Node 24 and PostgreSQL 17.

Loading diagram…

  • Wrongly typed input goes straight to the DB or hangs a regex.
  • Broken async sends errors to the wrong try/catch, or crashes the process.
  • Resources are the last stage but affect every other request in turn.
Page Question it answers Example mistakes
Async & errors Why aren’t errors caught, why does the process exit on its own? async in forEach; return without await inside try; fire-and-forget without .catch
Numbers, dates, strings Why is money off, dates off, ids changing value? count(*) returns "1"; new Date('2026-10-18') is UTC; timestamp columns without a timezone
Database & transactions Why are queries slow, data duplicated or updates lost? N+1; check-then-insert; BEGIN via pool.query
API & security Why does the API leak data or get abused? string concatenation into raw SQL; fetching objects by id without an ownership check; jwt.decode instead of verify
Performance & resources Why does it run fine in testing but get slow/OOM in production? pbkdf2Sync in a handler; Promise.all over 10k items; fetch without a timeout

If you’re new, read in the table’s order. If you’re experienced, jump straight to the checklist at the end of each page.

Loading diagram…

  • Comment with a link: “This is return without await”. The recipient sees the full example and consequences; the reviewer doesn’t re-explain.
  • Assign severity: mistakes that corrupt data or crash the process (fire-and-forget, float money, check-then-insert) are blockers; performance issues on rarely called paths may be nits.
  • Turn it into a lint rule/test when it recurs often: e.g., @typescript-eslint/no-floating-promises catches unhandled Promises.
  • New mistakes found in postmortems get added as a BAD/GOOD pair on the right page.

For the full review process, see Code review.

Topic Article
The event loop, why synchronous code blocks every request Node.js event loop
Doing transactions correctly with ORMs Transaction patterns
Input validation, secrets, injection Secure coding
Timeouts and retries for outbound calls Timeout budget

Next: Async & errors.