← ClaudeAtlas

n-plus-one-finderlisted

Find database queries running inside loops — the N+1 pattern that is invisible on seed data and quadratic in production — plus unbounded queries with no limit and repeated identical reads in one request. Use when a page is slow, before a launch, after adding a list view, or when database load rises without traffic rising.
sriptcollector/toolbay-skills · ★ 0 · Code & Development · score 72
Install: claude install-skill sriptcollector/toolbay-skills
# N+1 Finder ## Install Save this file as `~/.claude/skills/n-plus-one-finder/SKILL.md`, or `.claude/skills/n-plus-one-finder/SKILL.md` to scope it to one repo. Claude Code auto-discovers it. Invoke with `/n-plus-one-finder` or by asking "why is this page slow?". ## Why this exists N+1 is the most common serious performance bug in application code and the easiest to ship, because it is invisible exactly where you develop. With 10 seed rows it costs 11 fast local queries and nobody notices. With 10,000 rows and network latency it is 10,001 round trips and the page times out. It is also the bug that scales with your success. It appears the week traffic arrives, which is the week you can least afford to be debugging it. The tell is structural, not intuitive: **a query inside an iteration.** Find those and you have found most of it. ## Step 1 — Find queries inside loops ``` rg -n -B6 "await (prisma|db|knex|sequelize|supabase|pool)\." | rg -B6 "(\.map\(|\.forEach\(|for \(|for await|while \()" rg -n "\.map\(async" rg -n "for (const|await const).*\{[\s\S]{0,300}?await .*(find|select|query|get)" -U ``` Then read each hit, because the grep over-reports. You are confirming three things: 1. A query genuinely executes per iteration. 2. The collection is unbounded, or bounded only by something that grows. 3. The data could have been fetched in one query instead. `Promise.all` around per-item queries is **not** a fix. It converts a serial N+1 into a parallel one: still N querie