Back to all terms
Database
Databasebasic

N+1 Query Problem

A performance anti-pattern where fetching a list of N records triggers N additional queries to load related data, instead of using a single JOIN or batch query.

Also known as: N+1 select problem, lazy loading problem, query fan-out

Description

The N+1 query problem occurs when application code fetches a collection of parent records (1 query) and then iterates over each record to fetch its related children (N queries). For example, loading 50 blog posts and then issuing 50 separate queries to fetch each post's author. This results in 51 database round-trips instead of a single query with a JOIN or a batched IN clause. At scale, this causes devastating latency and connection pool exhaustion.

ORMs are the most common source of N+1 problems because they make it easy to access related objects through lazy-loaded properties without making the cost visible. In Prisma, use the include option to eagerly load relations. In SQLAlchemy, use joinedload() or selectinload(). In ActiveRecord, use includes() or eager_load(). The key is declaring upfront which relationships you need rather than relying on transparent lazy loading.

Detecting N+1 issues requires instrumentation. Enable query logging in development and look for repeating query patterns with varying parameters. Tools like Bullet (Ruby), nplusone (Python), and custom middleware that counts queries per request can catch these before they reach production. Set a query count budget per endpoint -- if a single API request issues more than 10-15 queries, investigate for N+1 patterns.

Prompt Snippet

Implement N+1 detection middleware that counts SQL queries per HTTP request and logs a warning when the count exceeds 15. In Prisma, enforce eager loading by using include/select for all relational queries and ban implicit relation traversal in application code. For GraphQL resolvers, implement DataLoader with per-request caching to batch and deduplicate database calls. Add integration tests that assert query count per endpoint using a query counter hook.

Tags

performanceormanti-patternquery-optimization