docs(specs): spec, plan and tasks for GraphQL query cost [INFP-739]
Jira: INFP-739. A GitHub issue for this work is not known.
This PR adds the design documents of the feature in dev/specs/infp-739-graphql-query-cost/. It changes no code. The implementation is in #11003, which targets this PR's branch.
TL;DR
- Problem: a team that renders artifacts or runs generators from GraphQL queries over a large data set cannot tell, before or after a run, how much work a query causes or which relationship field causes it. Infrahub records only the depth and height of each query, so an engineer has to trace a run to find the field that multiplies the database rows.
- What is needed:
- the actual nodes, resolver calls and database rows of each relationship field, returned when a request to
/graphqlor/api/querysends a header - an expected and a worst-case estimate of the same figures for each relationship field, built from peer statistics that a scheduled task computes from main
- the same estimate from the
InfrahubGraphQLQueryReportquery, without running the submitted query
- the actual nodes, resolver calls and database rows of each relationship field, returned when a request to
- Not decided yet:
- how old the statistics may be, which the refresh schedule sets
- whether
infrahub-private-testsneeds a CI change to run the synthetic data set - which trace and which customer the
CablingPlanLogicalfigures come from - a maintainer's confirmation of three changes in "Ask First" areas, listed below
Why an estimate from average peer counts is not enough
From spec.md, "Summary":
- The work of a query depends mostly on how many peers each relationship returns, and that number varies widely between nodes.
- On one customer's
CablingPlanLogicalquery, an estimate from averages gives about 23,000 single-relationship resolver calls, against an actual 183,000. Counting the devices at the first step and using averages after it gives about 254,000. - Neo4j's own statistics cannot give the number of peers of each relationship, because every relationship goes through the same
IS_RELATEDedge and Relationship vertex, and the relationship identifier is only a property.
The trace these figures come from is not linked, and the customer is not named in the sources.
Design documents in this PR
- spec.md: two P1 user stories, the functional requirements FR-001 to FR-018, the success criteria SC-001 to SC-004, the assumptions, what is out of scope and the open questions
- plan.md: the technical approach, the constitution check, the files to add and change, the design notes and the risks
- research.md: the facts the design depends on and the design decisions D1 to D12, for example:
- the name and values of the request header (D1)
- how the actual counts are recorded (D3)
- the content and cache layout of the statistics (D5)
- the counted first step (D9)
- the estimate algorithm (D10)
- data-model.md: the cache keys of the statistics, the estimation tree, and the estimate and actual counts of a field
- contracts/: the request header and the
extensions.query_costcontent, as a description and as a JSON schema, and the GraphQL contract ofInfrahubGraphQLQueryReport - quickstart.md: manual steps to check the feature on a development stack with the demo data
- tasks.md: 46 tasks in 7 phases
- critiques/critique-20261007-184332.md: a critique of the spec and the plan. Its findings are applied to the documents above.
- alignment-check.md: a check of spec.md against the INFP-739 brief. It found five minor additions and clarifications, and no requirement of the brief that is missing, weakened or contradicted.
- checklists/requirements.md: the quality checklist of the spec
Changes in "Ask First" areas that need a maintainer's confirmation
AGENTS.md, "Ask First" lists changes to ask about before they land. According to spec.md, "Governance gates crossed", the feature makes three of them:
- GraphQL schema change: a new
variablesargument and new estimate fields onInfrahubGraphQLQueryReport - API contract change: a new request header on
/graphqland/api/query, and newextensionscontent in the response - Authorization change: a read-permission check on
InfrahubGraphQLQueryReport, with no new permission
Not crossed:
- a database schema or migration change: the statistics are stored in the cache, not in the graph
- a new dependency
- a CI/CD workflow change in
opsmill/infrahub
The INFP-739 brief records the three changes as decided. According to tasks.md, "Before the PR leaves draft", the implementation PR is not marked ready before a maintainer confirms them. #11003 lists them with a checkbox for each.
Out of scope
From spec.md, "Out of Scope", among other items:
- limiting how many artifact and generator runs happen at once by their total estimated cost (related: INFP-689)
- sizing Cypher pages and loader batches from the estimate (related: INFP-502)
- Prometheus metrics, a single combined cost figure, and admission based on cost
- estimating the reads caused by display labels rendered from templates, profile values and permission filtering
- mutations
Changes that the implementation PR makes to these documents
#11003 updates some of these documents to match the code that landed, and adds two files:
tasks.md: 45 of the 46 tasks are ticked. T046, a PR inopsmill/infrahub-private-tests, is not done.data-model.md,research.md,plan.md,quickstart.mdandcontracts/: corrections and additions from the implementation, for example:- the point in the request where counting starts
- the response when no estimate can be computed
- the fields whose first step is not counted
- two quickstart instructions that did not work
pr-description.md: the description of #11003opsmill-implement-report.md: the implementation report, with the decisions that each implementation step flagged
Suggested review order
[CLAUDE RECOMMENDED – based on which documents each document refers to] spec.md, then contracts/, then plan.md with research.md and data-model.md, then tasks.md.
Sources
- INFP-739: the card and the idea brief in its comments
- the documents listed under "Design documents in this PR"
Generated with Claude Code