n-plus-one-killer
N+1 Killer
Find every N+1 in a Rails app and remove it. AI agents generate N+1s constantly — they write
.eachin a controller and call.authorin the view without realizing each row triggers a fresh SELECT. This skill makes the agent detect first, then fix, then prevent.
Why this matters
The single most common Rails performance issue. A list endpoint with 20 rows and a hidden N+1 issues 21+ queries per request. At 100 RPS that's 2100 queries/second the DB didn't need to handle. The fix is one method call; the detection is what people miss.
The opinion (Rails 8 default)
Detect with Bullet in development + test, fail tests on N+1, fix with
includes(orpreload/eager_loadwhen the trade-off is explicit). For the queries Bullet misses, add Prosopite. Reach forcounter_cacheand small denormalizations when the eager-loaded query is still too heavy.
Counter-position: gems like ar_lazy_preload and goldiloader automatically eager-load on first access in a loop. They eliminate the symptom but hide the cost — and they can over-eager-load (loading associations you only sometimes need). Use them only if the team has agreed to the trade-off; default to explicit eager loading.
Core patterns
Pattern 1: Detect with Bullet (dev + test)
Before (typical AI-generated controller, no detection in place):