Slot reservations — the math and the politics
Capacity-based slot reservation is the single biggest one-time FinOps lever in BigQuery for workloads with predictable diurnal patterns. Here is the math, the sizing process we used, and the two organisational traps that have killed more reservation moves than the math has.
The math
On-demand: $5 per TB scanned (US pricing as of mid-2026, varies by region). You pay per byte regardless of how much capacity you used.
Capacity (Enterprise edition): ~$0.06 per slot-hour, baseline + autoscale. 100 baseline slots running 24×7 is roughly $4,400 / month plus autoscale up-charge for bursts.
Break-even depends on workload shape. For a predictable batch workload scanning ~1 PB / month on-demand, that’s ~$5,000 / month. A 100-slot reservation that absorbs that workload at maybe 60-70% utilisation costs ~$4,400 — already cheaper. Add the autoscale band on top for the peaks and you save 20-30%.
For interactive ad-hoc workloads with low total bytes scanned, the math goes the other way. Reservation idle time is real cost.
The sizing problem
You can’t size a reservation correctly by averaging the on-demand spend. The reservation needs to absorb the peak of the regular workload, not the mean. Two complications:
-
Concurrency. A query that scans 100 GB might use 200 slots for 30 seconds or 50 slots for two minutes. The per-query slot-time integral is what matters, and INFORMATION_SCHEMA tells you both pieces.
-
Burst patterns. A reservation that’s flat 24×7 wastes money overnight. A reservation with autoscale handles bursts but the autoscale charge is on top of baseline; the question is what baseline to set so autoscale fires rarely enough.
The sizing query I run first:
SELECT
TIMESTAMP_TRUNC(creation_time, HOUR) AS hour,
SUM(total_slot_ms) / (1000 * 60 * 60) AS slot_hours,
COUNT(*) AS jobs
FROM `region-us`.INFORMATION_SCHEMA.JOBS_BY_PROJECT
WHERE creation_time > TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 90 DAY)
GROUP BY hour
ORDER BY hour;
Plot it. The 95th percentile of the hourly slot-hour is roughly the baseline you want. The peak above that is where autoscale lives.
The first organisational trap
The reservation purchase is a one-year commitment (or three, with a bigger discount). The engineering team can sign off on the recommendation, but the contract goes through finance and procurement. That’s a 2-4 week loop minimum.
In the gap, two things happen:
- The workload changes. Someone adds a new dashboard, a new pipeline, retires an old one. The reservation you sized in week 1 is too big or too small by week 4.
- Engineering enthusiasm fades. The team has moved on; nobody owns the post-purchase validation.
Mitigation: do the contract negotiation in parallel with the engineering sizing, not after. Set a calendar reminder for +30d to re-validate the reservation against actual usage. Don’t let the purchase be the end-state.
The second organisational trap
Reservations are billed monthly regardless of who runs the queries. If multiple teams share a project, the shared reservation needs an attribution scheme. Otherwise:
- Team A scales their workload 3×. The reservation runs hotter. Team B’s queries queue.
- Team A’s manager doesn’t see a cost spike because the reservation is flat-rate. Team B’s manager sees latency complaints they don’t understand.
We solved this with project-level reservation assignments where
politically possible, and with labels + a Looker dashboard that
showed slot_hours_consumed_by_team where the projects were
already shared. The dashboard alone — without changing billing —
shifted behaviour within a quarter.
When NOT to reserve
- Workload is genuinely ad-hoc. Data scientists running exploratory queries with high variance. The reservation is idle 60% of the time; on-demand is honestly cheaper.
- You’re early in a build-out. Workload is going to triple in six months. Lock-in is a bet on a shape that won’t hold.
- You haven’t done query optimisation yet. Reserving against the un-optimised workload buys 30% too much.
The right order is: optimise first, reserve second. The optimisation typically removes 20-40% of the workload, and that’s a 20-40% smaller reservation you commit to.
The 30-day check
After a reservation purchase, the +30d check is the most important moment. The questions to answer:
- Is the baseline saturated or idle most of the time?
- Is autoscale firing? How much, when?
- Are queries queuing at peak? (
pending_timein the JOBS view.)
If the baseline is idle most of the time and queries aren’t queuing, you over-bought. Most reservation contracts allow downward changes with notice; use them.
If queries are queuing at peak, you under-bought the baseline. Add slots or extend the autoscale ceiling.
The reservation is not a fire-and-forget purchase. Treat it the same way you’d treat any other infrastructure commitment — with a monthly review.