← Back to archive

Repo of the Day

GitHub - oniani1/queryguard: Detect N+1 queries at the driver level. Zero config. Works with any ORM.

Published: Jul 16, 2026

Open repository ↗

Detect N+1 queries at the driver level. Zero config. Works with any ORM. - oniani1/queryguard

Summary

queryguard (npm: qguard) is a TypeScript library that detects N+1 query patterns by monkey-patching the pg and mysql2 database drivers. It normalizes each SQL statement into a fingerprint, records queries into an AsyncLocalStorage context, and flags any fingerprint that repeats more than a configured threshold outside a transaction. It works with Prisma 7 (via @prisma/adapter-pg), Drizzle, Kysely, TypeORM, Knex, Sequelize, and raw pg or mysql2 code.

What it is useful for

queryguard is designed to catch N+1 patterns in tests before they reach production. The README notes that ORM-specific lint rules miss raw queries, cross-ORM projects, and code behind abstraction layers, while queryguard sees every query that reaches the driver.

Practical uses include:

  • Guarding a test suite with assertNoNPlusOne to flag the classic "list users, then fetch each profile" pattern.
  • Setting a hard query count cap with queryBudget for endpoints where the expected query count is known.
  • Detecting data-dependent scaling with assertScaling, which runs the same code at two cardinalities and flags any fingerprint whose count grows between them. By default it compares 2 vs 3 records with an automatic warmup run.
  • Attaching middleware in Express, Next.js (App Router), Hono, or Fastify to log or alert on N+1 patterns per request, with optional Sentry and Slack notifiers.

Documented limitations: Prisma 6 is not supported because it uses a Rust query engine that bypasses pg; pnpm monorepos can end up with multiple driver copies, in which case the README instructs passing the app's driver instance via install({ pg }); and queryguard only detects problems, it does not fix them.

How engineers can use it

The documented install and usage:

npm install qguard
import { assertNoNPlusOne } from 'qguard/vitest'

test('listing users does not N+1', async () => {
  await assertNoNPlusOne(() => handler(req, res), {
    threshold: 5,
    ignore: [/pg_catalog/],
  })
})

For request-level tracking in Express:

import { queryGuard } from 'qguard/express'
app.use(queryGuard({ mode: 'warn' }))

Note that Express cannot throw after a response is sent, so mode: 'error' degrades to warn there. By default queryguard is disabled when NODE_ENV=production; set QUERYGUARD_FORCE=1 to enable it. Full configuration, notifier setup, and middleware examples are in the repository README.