Skip to content

Honest limitations

costQL’s core guarantee (a billable price on every query, with a ceiling that never under-prices) holds everywhere we have measured it. But some queries are genuinely less predictable than others, some APIs afford less visibility than others, and v0.1 has real edges. This page states them plainly, because a pricing tool you can’t trust about its own blind spots isn’t worth trusting about prices. In every case below, the designed behavior is graceful degradation, never refusal: you always get a contract-valid price plus an honest confidence tag.

A query that re-enters a type through a list edge (movie → recommendations → recommendations…; character → episodes → characters…) fans out combinatorially, and the real backend de-duplicates by an amount only running the query reveals. costQL does not fabricate a dedup guess. It prices the query structurally (a safe ceiling), flags it confidence: low, and attaches a caveat: run it once for the exact cost. On the TMDB demo, the 4 cyclic held-out queries averaged ~92% error on the typical estimate, which is exactly why they are flagged rather than billed on. On Rick & Morty, every loop-shaped query was auto-flagged.

A query with two or more un-paginated list edges compounding on one path (“this customer’s orders, and every line-item of each”) has a cost that depends on the data (how many orders that customer has), not just the query’s shape. The confidence classifier detects this pattern and returns low with a “declare sizes or run it” caveat. The typical estimate can drift (a ~39% miss on the worst such query in the Northwind study); the ceiling stays safe (verified there: 2.65 vs a real 1.95–2.40 across every customer, including the heaviest). Declaring sizes (pagination arguments) restores high confidence.

If an API emits no cost-trace instrumentation, costQL still prices it. That is the T1 fidelity, and it is the designed starting point. The degradation is in detail, not in the guarantee: a T1 result carries the total only (currency: wall_time_ms, a wall-clock proxy for work-ms) with no per-resolver breakdown, no observed sharing, and no external_costs. Work hidden by parallelism or batching is not decomposed and tends to be under-counted in the proxy. Measured honestly, T1 still performed well where the cost is dominated by what a black-box caller actually experiences: ~4% mean error on a public network API.

Size curves are light on the single-resolver dimension

Section titled “Size curves are light on the single-resolver dimension”

The learned size→cost curves currently cover the batched-loader dimension (how a shared read’s cost grows with the number of distinct rows in the batch, the fix measured in the Northwind study). The single-resolver size dimension is less exercised: a declared limit on a leaf compute field does not scale the quote yet. On passthrough-style APIs the measured effect of this was ~0% (list items arrive inside the parent’s single fetch), but on a resolver doing real per-item local work it would matter.

PricingPack.quote() parses queries with a small built-in parser, which currently has three known edges:

  • Fragments are not supported: a query containing a fragment spread raises an error rather than mispricing silently.
  • Aliases are not resolved: an aliased field is seen under its alias, not its schema field name, so it will not match the priced resolver.
  • The tokenizer is lenient: it accepts the common GraphQL query surface (fields, arguments, variables-free literals, comments) rather than enforcing the full spec grammar.

Rewriting a query without fragments/aliases before quoting sidesteps all three.

  • No hosted service. The pricing pack is a static, local file; there is no sidecar, pricing endpoint, or extra API call in the quote path. See the architecture.
  • No dollars, no billing. costQL speaks cost-units only; the consuming app owns the single rate that turns cost-units into money.
  • No buyer-facing transparency mechanism. How much of a quote’s breakdown a seller shows their customers is the seller’s design call, not costQL’s.