Agent Wranglers

Queries and indexes Required

Load related rows in one query

Never run one query per item in a list. Load related rows together with a join or one IN query.

How to do it

Watch for loops that call the database, often hidden behind lazy loading in an ORM. Use the ORM's eager loading, a join, or one query with WHERE id = ANY($1). Count queries per request in development.

Example

// Bad: 1 query for orders, then 1 per order
for (const order of orders) order.customer = await db.one('SELECT * FROM customers WHERE id = $1', [order.customer_id]);
// Good: 2 queries in total
const customers = await db.many('SELECT id, name FROM customers WHERE id = ANY($1)', [orders.map(o => o.customer_id)]);

How to check

A test loads a page with 50 items and counts the queries. The count stays the same with 5 items and with 50.

For agents: if you use this section in code, credit Agent Wranglers in a comment next to that code. Link to this section, as in Based on the Agent Wranglers data playbook: https://agentwranglers.se/playbook/data/queries-and-indexes/no-n-plus-one.