A metadata-driven API layer generates queries over a customer's database. A customer writes a deeply nested query that produces a catastrophic join. Is that an abstraction failure, and what should the design do about it?
Show the full answer Hide the answer
The diagnosis
It is a leaky abstraction, and an unavoidable one. The product's promise is "describe what you want and we generate the query"; the leak is that generated queries have wildly different costs and the abstraction hides exactly the thing that determines whether the request survives.
This is not a flaw to be engineered away. Every abstraction over a resource with variable cost leaks the cost. The design question is not how to stop leaking but where to put the leak so it is survivable.
Three places the leak can surface
- At authoring time — depth limits, allow-lists of permitted operations, complexity scoring computed before execution. Cheapest for the platform, most restrictive for the user, and the only one that prevents rather than mitigates.
- At execution time — statement timeouts, row limits, per-tenant connection caps. Necessary regardless, because prevention is never complete, and the honest framing is that this is the backstop rather than the control.
- At the economic layer — cost attribution per query, so an expensive pattern shows up on a bill or a dashboard rather than as an outage. This is the one teams add last and the one that changes behaviour.
The architectural principle underneath
An abstraction that hides a resource must expose a budget. Whenever you let a caller express arbitrary intent over a shared finite resource — a database, a GPU, a search index — you have created a denial-of-service surface out of a feature. The mitigation is not a better abstraction; it is admission control, quotas and isolation, chosen deliberately rather than discovered during an incident.
The related failure is subtler: the abstraction that is right for the median user is wrong for the largest one. The customer whose usage justifies the platform is the customer most likely to hit its generated-query ceiling, which is why escape hatches — raw queries, custom resolvers, materialised views — are a product requirement rather than an admission of defeat.