An embedded analytics feature inside a design-collaboration platform in Canva's mould serves 4000 customer workspaces from shared tables on one warehouse. The largest workspace holds 38% of all rows and its dashboard refreshes drive the p95 every other customer sees. The team moves that workspace to its own compute and its own copy of the tables. p95 falls by half. What have they given up and when does the bill arrive?
Show the full answer Hide the answer
What the move actually buys
Three things worth having. The noisy neighbour is gone by construction rather than by politeness, so one customer's refresh storm cannot move anyone else's p95. Cost becomes attributable, because that workspace's compute is a line item instead of a share of a pool. And the big tenant can be tuned - its own clustering, its own refresh cadence - without trading off against 3999 others.
What is paid
- Two deployment targets for every change. A new column, a backfill, a permission change and a retention rule now happen twice. The second one is forgotten eventually, and the drift is found by a customer.
- Idle compute. A shared pool amortises peaks across 4000 workspaces. A dedicated cluster is paid for while its single tenant sleeps, which for a design tool with a working-day pattern is most of the week.
- Lost sharing. Result cache, materialised aggregates and compaction work that served every tenant now run twice over two sets of files, so maintenance compute rises rather than moving.
- A precedent. The second-largest workspace is now the loudest neighbour, and its account manager has heard what the largest one got.
When the bill arrives
At the third whale, not the first. One exception is a configuration; three exceptions with slightly different shapes are a platform you did not plan to build, and the team is now operating per-tenant capacity for a handful of customers whose combined revenue may not cover the engineering.
It also arrives at the next schema migration, where the shared path and the dedicated path diverge for a day, and at the first incident that affects only one tenant - because the runbooks, alerts and dashboards were written for one estate.
How to keep the option to reverse
Make placement data, not code. One transformation codebase, identical DDL, and a tenant-to- compute mapping held in a table the platform reads. Then dedicating a tenant is a row change and undedicating is the same row change back. Define two or three placement tiers rather than special-casing one customer, and make the promotion rule explicit: a tenant moves to its own compute above a published share of workload, and moves back below it.
Keep the data layout tenant-aligned in both tiers - tenant as the leading clustering key - so a move is a copy rather than a re-model.
When this is the wrong answer
Below roughly 10% of workload, a tenant is not a whale and dedicating compute is cost without benefit. Try the cheap controls first: a per-tenant concurrency cap, a query cost ceiling, a scheduled refresh window that spreads the storm, and tenant-aligned clustering so the big tenant's queries stop scanning everyone's files. Those fix most noisy-neighbour complaints at a fraction of the operating cost, and they are reversible in an afternoon. Dedicate when the tenant has a contractual latency commitment or a residency requirement, where the cheap controls cannot reach.