How would you design BigQuery slot reservations and assignments for several teams sharing one organization?
answer
- capacity, pools, and bindings are three things
- isolate by latency contract, not by team
- commit the floor, autoscale the peak
- walls guarantee performance and waste slots
- under slots, attribution is something you build
basics
~20 sBuy capacity once in an admin project, then split it into a few reservations by workload class — production pipelines, BI, ad-hoc — bind projects or folders to them with assignments, commit only the confident floor, and let autoscaling and idle-slot sharing absorb the rest.
solid answer
~50 sCapacity is purchased in an **admin project** and carved into **reservations**; **assignments** bind an organization, folder or project to a reservation for a job type such as QUERY or PIPELINE. Design along workload class, not org chart: nightly ELT that must hit an SLA gets its own reservation so an analyst cannot starve it; BI gets one sized to daytime concurrency; exploration and sandboxes are often best left unassigned, falling back to on-demand where idle time costs nothing. Commit one- or three-year capacity only to the floor you are confident about and let autoscaling maxima cover peaks. Leave `ignore_idle_slots` at its default so reservations can borrow each other's idle capacity — over-isolating fragments the pool and wastes slots. Then monitor: `INFORMATION_SCHEMA.JOBS_TIMELINE` for concurrency shape and queueing, plus job labels for chargeback, because under capacity pricing cost attribution is something you build.
code
text · 11 linesadmin project: bq-capacity (region US)
commitment: 1-year, 600 slots autoscale headroom above baseline
reservation etl-prod baseline 400 max 600 idle-sharing on
assignment project/etl-prod job_type QUERY
assignment project/etl-prod job_type PIPELINE
reservation bi-prod baseline 200 max 900 idle-sharing on
assignment folder/analytics job_type QUERY
(no assignment) sandbox-*, notebooks -> on-demand per-byte billinggo deeper
Know the vocabulary chain: capacity is bought in an admin project, split into reservations, and bound to projects by assignments; anything unassigned falls back to on-demand.
Explain baseline versus autoscaling maximum, what idle-slot sharing does, and why an unassigned project silently bills per byte instead of failing.
Show how you size each reservation from measured slot concurrency, isolate the SLA workload, and monitor queueing and JOBS_TIMELINE after cutover to confirm the design.
Own the isolation-versus-utilization tradeoff, the multi-year commitment risk, which workloads deliberately stay on-demand, and how compute cost is attributed back to teams once bytes stop being billed.
## The objects you are designing with Three things, in a chain. **Capacity** is bought in one project — the admin project — either as pay-as-you-go autoscaling or as a one-year or three-year commitment, at a chosen edition. A **reservation** is a named pool of that capacity, with a baseline slot count and optionally an autoscaling maximum. An **assignment** binds a consumer — an organization, a folder, or a project — to a reservation for a specific job type (QUERY for queries, PIPELINE for load and export jobs, and a couple of others). Anything with no applicable assignment falls back to on-demand per-byte billing. That fallback is a design tool, not an accident. ## Split by workload class, not by org chart The instinct is one reservation per team, and it is usually wrong. Teams are a billing boundary; workloads are a contention boundary. What actually needs isolation is work with different latency contracts: - **Production pipelines** with an SLA — the nightly ELT that must finish before the business opens. Give it its own reservation with a baseline sized to its measured demand, so nothing an analyst does can push it past its window. - **BI and dashboards** — many small-to-medium concurrent queries during working hours. Size for daytime concurrency; a modest baseline with a generous autoscaling ceiling matches the shape well. - **Ad-hoc and exploration** — bursty, unpredictable, low duty cycle. Frequently the right answer is *no reservation*: leave those projects on on-demand, where idle costs nothing, and bound the risk with per-job byte ceilings and daily quotas instead. A small number of reservations is a feature. Every extra pool is capacity that can be idle while another pool queues. ## Commit only the floor Commitments discount capacity in exchange for locking spend for one or three years. Size the commitment to the demand you are confident persists — the level you would be embarrassed to be without — and cover everything above it with autoscaling, which costs more per slot but only while running. Committing to the observed peak is the classic and expensive mistake, and it is worse than overspending on-demand because idle committed slots appear on no query's bill; nobody sees the waste unless someone goes looking. ## Let the pools share Each reservation has an `ignore_idle_slots` property. Left at its default, jobs in one reservation may borrow slots that other reservations in the same admin project are not currently using, which is how you get isolation of the *guaranteed* floor without paying for isolation of the *peak*. Setting it to TRUE caps a reservation at its own slots and refuses borrowed capacity — appropriate only when you need strictly reproducible performance and are willing to pay for idle. In a multi-team design, sharing on by default plus a properly sized baseline for the SLA workload usually beats hard walls everywhere. ## Sizing from evidence Never size from intuition. Sum `total_slot_ms` per hour from `INFORMATION_SCHEMA.JOBS` and divide by the hour's wall-clock milliseconds to get average concurrent slots; do it per project so each candidate reservation has its own curve. Read the sustained level as the baseline and the peaks as the autoscaling maximum. Then, after cutover, watch `INFORMATION_SCHEMA.JOBS_TIMELINE`, which reports slot consumption in time slices, to see whether the shape you designed for is the shape you got, and watch job queueing to catch a baseline set too low. ## Attribution and chargeback Under on-demand, cost attribution is free: every job carries its own billed bytes. Under capacity, the invoice is for slots over time and does not decompose itself. You rebuild attribution one of two ways: a reservation per billing unit — clean but fragmenting — or shared reservations plus **labels** on jobs, apportioning cost by each team's share of `total_slot_ms`. Decide this before migrating; retrofitting labels onto pipelines after finance asks for a breakdown is unpleasant. ## Failure modes to design against **Baseline too small, autoscale ceiling too high** — everything technically works while the bill drifts upward invisibly. **Too many reservations** — several pools idle while one queues. **No fallback path** — a project accidentally unassigned suddenly bills per byte, which is not a fault but is a surprise if nobody expected it. **One pool for everything** — cheapest to run, until the quarterly backfill collides with Monday morning dashboards and there is no lever to pull. ## What a strong answer sounds like Measure, split by latency contract rather than by team, commit the floor and autoscale the peak, keep idle sharing on, leave spiky exploration on-demand, and build attribution deliberately. The tradeoff you are being asked to own is isolation versus utilization: every wall you build guarantees somebody's performance and wastes somebody's slots.
- What does setting ignore_idle_slots to TRUE on a reservation do?It caps that reservation's jobs at its own slot capacity, refusing idle slots offered by other reservations in the same admin project. You get strictly predictable capacity at the cost of leaving borrowed capacity on the table. The default leaves sharing on, which usually gives better overall utilization.
- The nightly ELT keeps missing its window in a shared reservation. What do you change?Give the ELT its own reservation with a baseline sized to its measured slot demand and assign that project to it, so daytime and ad-hoc work cannot compete for the same floor. BigQuery has no per-team priority weight inside one reservation, so isolation is the mechanism, not prioritisation.
- How do you charge slot cost back to teams sharing one reservation?Label every job by team, pipeline or asset, then apportion the reservation's cost by each label's share of `total_slot_ms` from `INFORMATION_SCHEMA.JOBS`. The alternative is a reservation per billing unit, which attributes perfectly but fragments capacity and raises total slots purchased.
- Should exploratory analyst projects get a reservation?Often not. Their usage is bursty and low duty cycle, so a reservation sits idle most of the time while on-demand costs nothing when unused. Bound the risk instead with maximum_bytes_billed defaults, daily query-usage quotas, and require_partition_filter on the big tables.
saying these in an interview costs you the question
- Creates one reservation per team by default
- Commits multi-year capacity sized to the peak
- Turns off idle-slot sharing everywhere for safety
- Assumes cost attribution still works automatically under slots
- Expects per-query priority to isolate workloads inside one reservation