Databases
N+1 Query Problem
Fetching a list with one query, then firing one more query per row — 1+N round-trips that turn a 5ms page into a 500ms one. It hides behind ORM lazy loading, which makes each extra query invisible in the code. The fixes are eager loading, joins or batching; the diagnosis is counting queries per request.
Purpose
The N+1 problem is a query pattern, not a database fault: load 100 orders (1 query), then access order.customer in a loop and the ORM helpfully loads each customer on demand (100 queries). Each one is fast; the sum is not — every round-trip pays network latency, and latency × N dominates. It exists because lazy loading makes the expensive thing syntactically free.
When to Use It
Anywhere a list is rendered with data from a related table: order lists showing customer names, posts with authors, dashboards summing children per parent. GraphQL is a second breeding ground — naive per-field resolvers re-create the pattern one level deeper, which is why DataLoader-style batching exists.
Trade-offs
The fixes have their own costs. Eager loading (include/JOIN) can over-fetch — joining four one-to-many relations multiplies rows before they collapse back. Batching (WHERE id IN (…)) adds a coordination layer. And sometimes two queries genuinely beat one enormous join; the goal is a bounded, small number of queries per request, not exactly one.
Implementation
Declare relations up front — Prisma's include, SQL JOINs, or an IN-batch keyed by the parent IDs; in GraphQL, put DataLoader behind every relation resolver. Then make the invisible visible: log query counts per request in development and alert when a request crosses a threshold — N+1 regressions sneak back in one innocent property access at a time.