Performance
- Node.js
How fast a system responds and how much it can do — improved by measuring first, then fixing real bottlenecks like slow queries, N+1 access, and missing caches.
What you'll understand
- The difference between latency and throughput
- Common backend performance bottlenecks
- Why you measure before optimizing
Explanation
Performance is about how quickly a system does its work and how much it can do at once. Two measures capture it: latency, how long a single request takes, and throughput, how many requests it can handle per unit of time. They are related but distinct, and which matters more depends on the goal. Performance is about speed at a given load; scalability (see Related Topics) is about coping as that load grows.
On the backend, a few bottlenecks account for most slowness. The database is the usual suspect: missing indexes turn quick lookups into full scans, and the N+1 query problem, running one query per item in a loop instead of a single query, quietly multiplies database round-trips. Blocking the event loop with heavy synchronous work stalls everything (a Node.js concern from earlier modules), and repeatedly recomputing or refetching the same data wastes time a cache could save.
The unbreakable rule, exactly as with frontend performance (see Related Topics), is measure before optimizing. Intuition about what is slow is usually wrong, so profile the system, read the query plans, and find the real bottleneck before changing anything. Then apply the targeted fix, add an index, batch the N+1 into one query, cache an expensive result, and measure again to confirm it helped. Optimising code that was never the problem adds complexity for nothing.
Examples
The N+1 problem: a query per item versus a single query for all of them:
// N+1: one query per order (slow)
for (const order of orders) {
order.user = await db.user.findUnique({ where: { id: order.userId } });
}
// Fixed: one query for every needed user
const users = await db.user.findMany({ where: { id: { in: userIds } } });Common mistakes
- Optimizing based on a guess instead of a measurement.
- The N+1 query pattern: querying in a loop instead of in one batch.
- Missing indexes on columns used to filter or join (see Related Topics on databases).
- Blocking the event loop with heavy synchronous work.
Best practices
- Measure and profile to find the real bottleneck before optimizing.
- Fix slow database access first: add indexes and batch N+1 queries.
- Cache expensive or frequently repeated work.
- Re-measure after each change to confirm it actually helped.
Further reading
- Microsoft, Performance efficiency — https://learn.microsoft.com/en-us/azure/well-architected/performance-efficiency/
- Microsoft, Caching best practices — https://learn.microsoft.com/en-us/azure/architecture/best-practices/caching