DEV Community

Cover image for Your endpoint returns 200 OK. It also ran 51 queries.
Benziza
Benziza

Posted on

Your endpoint returns 200 OK. It also ran 51 queries.

A 200 OK doesn't tell you how much database work happened behind the response.

An endpoint can return the exact same JSON, pass all its integration tests, and still quietly go from 1 database query to 51.

That's the regression I wanted to catch.

QueryGuard.NET

I built QueryGuard.NET to make EF Core query behavior part of the test contract.

It records EF Core commands executed inside a request or test, groups repeated SQL into fingerprints, and lets you enforce query budgets.

await using var scope = QueryGuardScope.Start(
    "GET /api/companies",
    QueryGuardPolicy.Create("companies")
        .WithMaxOccurrencesPerFingerprint(5));

await client.GetAsync("/api/companies");

QueryGuardAssert.Passes(
    await scope.CompleteAsync());
Enter fullscreen mode Exit fullscreen mode

In the sample project:

51 queries
same fingerprint executed 50x

Budget: 5
Result: FAIL
Enter fullscreen mode Exit fullscreen mode

After fixing the query:

51 queries -> 1 query
Enter fullscreen mode Exit fullscreen mode

Same response. Different database behavior.

QueryGuard deliberately reports repeated-query candidates, not "N+1 detected", because repeated SQL is evidence of an N+1 pattern, not proof.

Parameter values aren't captured by default, and the current preview only observes EF Core.

SQLite and PostgreSQL are integration-tested in CI.

Try it

https://github.com/Benziza/queryguard-dotnet

The project is MIT licensed and currently available as 0.1.0-preview.1.

One design question I'm especially interested in:

Would you rather enforce a total query count, or a per-fingerprint budget like “this query pattern may execute at most 5 times”?

Feedback from real EF Core codebases would be very useful.

Top comments (0)