Query Surface Volatility
How fast a product invents query shapes it did not have before - the workload fact that decides whether a purpose-built physical layout or a general query planner is the cheaper bet.
A team picks a key-value store because write volume is expected to be large. Eight months later someone wants "orders by supplier by week where the shipment was late", a question nobody imagined at design time. There is no index for it, the partition key is the customer id, and all three answers available are bad: add a secondary index and pay for a second copy, maintain a denormalised table, or scan.
The decision that went wrong was not the choice of store. It was assuming the set of queries was known. Access-pattern-driven modelling is the right method for a key-value or wide-column design, and it has a precondition: the patterns must be enumerable and stable. Query surface volatility is the rate at which that precondition fails.
Why it matters
Volume is the reason usually given for leaving a relational database, and it is the wrong one, because volume is the single problem sharding solves without changing the query model. What a distributed key-value store asks you to give up is the ability to answer a question you did not design for. A planner over normalised tables pays a per-query cost to buy exactly that option.
Stated as a rate the decision becomes measurable. Count the distinct query shapes in production and how many appeared last quarter. A handful unchanged for 2 years is low volatility and the purpose-built layout is the cheaper bet; a team shipping a new report every sprint is high volatility, and each new shape costs an index, a denormalised copy or a migration.
Implementation patterns
- Count the shapes, not the queries. Group by predicate and join structure rather than by SQL text. Most systems have 20 to 60 distinct shapes and a handful carrying over 90% of volume.
- Split by volatility rather than by entity. Keep the stable high-volume shape in a purpose-built store and the long tail in the relational database, with a change-data-capture feed absorbing analytical shapes.
- Record the assumption. "Chosen against 14 query shapes as of 2026-03" plus the trigger "more than 5 new shapes in a quarter" converts a permanent-looking decision into a monitored one.
Industry example
Notion's 2021 sharding of its Postgres database into 480 logical shards is instructive for what they did not do. A block-structured product with permission inheritance looks like a document database on the surface, but its queries are recursive tree traversals with authorisation predicates. They kept the relational engine and changed only the physical distribution.
Figma's databases team reached the same conclusion in 2024: they built their own sharding layer rather than adopt a distributed SQL engine, and their colocation groups exist so joins and transactions survive within a sharding key.
Failure scenarios
- The unforeseen report. A query shape with no supporting index becomes a full scan, and the first symptom is a cost line rather than an error.
- Index sprawl. Each new shape gets a secondary index; write amplification grows with the index count and the write throughput that justified the store choice quietly disappears.
- Divergent denormalised copies. Two tables holding the same fact drift after a partial failure, and nothing detects it until a customer reports the mismatch.
Trade-offs
| Choose | Gains | Pays |
|---|---|---|
| Purpose-built layout at low volatility | Predictable single-digit-millisecond reads | An index or a copy for every unforeseen query |
| General planner at high volatility | New questions without a physical change | Planner cost per query and sharding work for writes |
| Split by volatility | Each workload in the store that suits it | Two stores and a sync path that can diverge |
When not to use it
Do not use volatility as the argument when one access pattern genuinely dominates and has not changed in years — a session store, a feed cache, a device telemetry sink. There the purpose-built layout wins on every axis and a planner is dead weight. Volatility also says nothing about write volume: a high-volatility workload can still outgrow one machine, which is a sharding decision rather than a model decision.
Interview question
Q: A team proposes moving the orders table from Postgres to a wide-column store because order volume will grow 10x. What do you ask them, and what would change your answer?
What a strong answer covers: 10x volume is a sharding and indexing question rather than a model question, so ask what the current bottleneck is — writes, working set or one specific query. Then ask for the count of distinct query shapes and how many are new this year. If orders are read by id and by customer only, and have been for years, the move is defensible and should be scoped to that one table. If finance, support and operations each query orders differently, the cheaper path is sharding the relational store with a change-data-capture feed for analytical shapes.
Quick check
Quiz: Which fact decides between a purpose-built key-value layout and a relational planner: data volume, or the rate at which new query shapes appear? The rate of new shapes; volume is what sharding addresses.
Flashcard: Why is "we need scale" a weak argument for leaving SQL? — Sharding scales a relational store without changing the query model, while the key-value move costs you every query you did not design for.