Synthetic Industry

Inspectable example · updated 2026-10-11

Synthetic query-count record for one endpoint: 101 queries to 2, with a ceiling test that fails on the old code

An invented before and after for a list endpoint, run in a small invented Django project: the query counts, a ceiling test written with CaptureQueriesContext, and the response comparison.

An example, not a customer case study. Scope and evidence limitations are described below.

The invented endpoint

Everything below is invented for illustration. It is not a measurement of any real system and not a customer delivery. The counts were produced by running the code below in a small invented Django 5.2 project on SQLite. An endpoint lists 50 invented orders, each with its customer name and its line items. The endpoint is public and uses no session, so the count is the endpoint's own queries.

If the matrix is wider than the box, scroll horizontally to read every column. Keyboard: focus the matrix and use Left/Right.

GET /orders/?page=1   (50 orders on the page, 2 line items each)

BEFORE: 1 query for orders
        + 50 queries for each order's customer      (lazy load per row)
        + 50 queries for each order's line items    (lazy load per row)
        = 101 queries, all but the first repeating with a different id

CHANGE: orders.select_related("customer").prefetch_related("lines")

AFTER:  1 (orders joined to their customers) + 1 (line items for all 50 orders)
        = 2 queries; ceiling agreed at 3 to leave one query of headroom

The test that keeps it fixed

The queries are captured around the request with the same filters the real requests use, so a hidden re-query fails the test. Django's assertNumQueries asserts an exact number: assertNumQueries(3) would fail on the changed code with "2 != 3". A ceiling needs the queries captured with CaptureQueriesContext and the count compared with assertLessEqual. The test is run on the old code first and must fail there.

If the matrix is wider than the box, scroll horizontally to read every column. Keyboard: focus the matrix and use Left/Right.

from django.db import connection
from django.test.utils import CaptureQueriesContext

def test_order_list_query_count(self):
    make_orders(50)                    # synthetic seed data
    with CaptureQueriesContext(connection) as ctx:
        response = self.client.get("/orders/?page=1")
    self.assertEqual(response.status_code, 200)
    self.assertLessEqual(len(ctx), 3)  # agreed ceiling

result on original code: FAILS  (101 is not less than or equal to 3)
result on changed code:  PASSES (2 queries, ceiling 3)

an exact count instead:  with self.assertNumQueries(2): ...
  (fails on 3 queries and also on 1)

What else is checked

Acceptance has more than the count.

  • The response body is identical to the original for page 1 and for a page with only 3 orders, including order of items.
  • Rows and columns loaded are reported before and after, so a join that pulls in far more data is visible.
  • Any relation deliberately left lazy is listed with the reason.
  • A second run with 500 invented orders in the table still makes 2 queries for a page of 50.
  • If the endpoint needs a login or uses database sessions, the request also loads the session and the user, and the agreed ceiling counts those queries.

Limits and the priced enquiry

An exact count breaks on harmless change, so the agreed ceiling leaves a little headroom; where you would rather be told about any change, an exact count is the choice and the test is written that way. This example is not a measurement of a real application. The fixed-scope endpoint job covers one endpoint in Django, Rails or SQLAlchemy at £245 as an untested proposal, paid after you sign off; send the framework version and the query count, never code or data.

Sources and limits

  • Django 5.2: Testing tools, assertNumQueries Checked 2026-10-11.
    • assertNumQueries(num, ...) asserts that num database queries are executed, for a function call or inside a with block.
  • Django 5.2 source: django/test/testcases.py Checked 2026-10-11.
    • assertNumQueries compares the number of captured queries with the number given using assertEqual, so it fails on fewer queries as well as on more.
  • Django 5.2 source: django/test/utils.py Checked 2026-10-11.
    • CaptureQueriesContext(connection) is a context manager that records the queries run on a connection while it is active; len() of it is the number captured and captured_queries lists them.
  • Django 5.2: QuerySet API Checked 2026-10-11.
    • prefetch_related with two relationships such as pizzas and toppings uses separate queries, and filtering a prefetched manager sends a new query.