Skip to content

rust.n_plus_one

Performance High

Detects N+1 query patterns where database queries are executed inside loops.

N+1 queries:

  • Kill performance — 100 items = 101 queries
  • Overwhelm databases — Connection pool exhaustion
  • Increase latency — Linear time complexity
// ❌ Before (N+1 query pattern)
async fn get_users_with_orders(db: &Pool) -> Vec<UserWithOrders> {
let users = sqlx::query_as!(User, "SELECT * FROM users")
.fetch_all(db).await?;
let mut result = Vec::new();
for user in users {
let orders = sqlx::query_as!(Order,
"SELECT * FROM orders WHERE user_id = ?", user.id)
.fetch_all(db).await?; // Query per user!
result.push(UserWithOrders { user, orders });
}
result
}
// ✅ After (batch query with JOIN)
async fn get_users_with_orders(db: &Pool) -> Vec<UserWithOrders> {
let rows = sqlx::query!(
"SELECT u.*, o.* FROM users u
LEFT JOIN orders o ON o.user_id = u.id")
.fetch_all(db).await?;
// Group by user
rows.into_iter()
.group_by(|r| r.user_id)
.map(|(_, group)| /* build UserWithOrders */)
.collect()
}
  • SQLx queries inside loops
  • Diesel queries per iteration
  • Missing eager loading patterns

Unfault suggests JOIN queries or batch fetching strategies.