GPU Economics & Capacity Planning
Deep dive: the systems-literacy round
GPU economics fundamentals
After this you can reason about what actually drives GPU cost.
A GPU costs roughly the same whether it runs at 90% or 9%. That one fact reshapes how you think about every dollar of Cursor's inference bill.
Inference is the dominant COGS line at a company serving 1M+ developers and the asset behind that line is a fleet of accelerators that are expensive to acquire, hungry for power and impossible to pause. Unlike a CPU box you can scale to zero, a reserved H100 bills the same per hour at idle as under full load. So the real cost question is never just "how many GPUs" - it is "how busy are the ones we already pay for."
When a systems-literacy interviewer asks what drives GPU cost, they want the cost structure, not a list of part numbers. There are four levers and idle time is the one that quietly wastes the most.
- Acquisition / amortization
- The card itself, amortized over its useful life - fixed whether you use it or not
- Power and cooling
- High sustained draw per accelerator; a real line in any owned or colo footprint
- Idle time
- Hours you pay for and get nothing back - the single biggest waste lever
- Acquisition lead time
- Not a dollar directly, but supply scarcity forces commitments months ahead of demand
Idle time is the lever you manage; the other three are mostly given to you.
Reserved vs. on-demand vs. serverlessthe buy decision is a bet on demand certainty
The cheapest hour comes from committing ahead of time and the most flexible hour comes from buying it the moment you need it. Choosing the mix is a bet on how confident you are in the forecast.
Interactive diagram. Tab through its regions; each focused region shows its detail in the panel below.
The buy decision is a bet on demand certainty - pick the column that matches your confidence in the forecast.
- Mode
- Reserved / committed
- Cost per hour
- Lowest
- Risk
- Stranded spend if demand misses the commitment
- Best for
- Predictable production baseline
- Mode
- On-demand
- Cost per hour
- Higher
- Risk
- Price volatility; capacity may not be there at peak
- Best for
- Spiky load, uncertain demand
- Mode
- Serverless / per-call
- Cost per hour
- Highest per unit
- Risk
- Cold starts, less control over latency
- Best for
- Burst and experimentation
| Mode | Cost per hour | Risk | Best for |
|---|---|---|---|
| Reserved / committed | Lowest | Stranded spend if demand misses the commitment | Predictable production baseline |
| On-demand | Higher | Price volatility; capacity may not be there at peak | Spiky load, uncertain demand |
| Serverless / per-call | Highest per unit | Cold starts, less control over latency | Burst and experimentation |
Reserved trades flexibility for price; on-demand and serverless absorb burst and experiments cleanly.
The number that ties this together is utilization. Reserved capacity only beats on-demand if you actually keep it busy. Run a committed cluster at 20% and you have paid the low per-hour rate on mostly dead hours, which is often worse than on-demand at the volume you really used.
Reserved capacity earns its discount somewhere around 60-80% sustained utilization. Below that band, the per-hour saving gets eaten by idle hours and on-demand would have been cheaper for the work you truly did. Above it, the committed cluster's effective cost per computation drops sharply because you are spreading a fixed bill across far more useful work. State the band, then say it depends on the specific discount and demand shape - that nuance reads as real FinOps experience.
GPUs vs. other accelerators
You do not need to design silicon, but you should reason about the rough fit by workload. Training and large-context prefill are throughput jobs that reward raw compute; tens-of-millisecond inference is a latency job where the constraint is response time, not aggregate FLOPs.
Long, throughput-bound jobs
Top-end interconnect and memory matter
Lives in R&D spend, not production COGS
Latency-tolerant, can batch hard
Optimize for cost per request
Highest utilization is achievable here
Tens-of-ms budgets (tab prediction)
Batching headroom is tight
You pay for responsiveness, not throughput
Do not conflate cheaper-per-hour with cheaper-overall. The trap question is "reserved is discounted, so we should reserve everything, right?" The honest answer is no: reserving capacity you cannot keep busy converts a flexible cost into stranded spend. Anchor on effective cost per useful computation, not the sticker per-hour rate.
Takeaway. A GPU bills the same idle or busy, so the cost question is utilization, not headcount - reserved capacity only beats on-demand once you sustain it in the 60-80% band.
Self-check
QWhich statement best captures why idle GPUs are the biggest waste lever?
Inference serving & latency
After this you can connect serving mechanics to cost and SLAs.
Cost per inference is not a property of the model. It falls out of four serving decisions made together: model size, utilization, batching and routing.
On the systems round you will be expected to reason fluently about serving without writing kernels. The mechanism that ties throughput to cost is batching: the GPU runs many requests through one forward pass, so the fixed cost of that pass is shared. Bigger batches mean lower cost per request. They also mean a request may wait for the batch to fill, which adds latency. That tension is the heart of inference serving.
- Lever
- Larger batches
- Effect on cost/request
- Lower (shared forward pass)
- Effect on latency
- Higher (queue + bigger pass)
- Tension
- Throughput vs. responsiveness
- Lever
- Smaller / routed model
- Effect on cost/request
- Lower for simple queries
- Effect on latency
- Lower (less compute)
- Tension
- Quality vs. cost on hard queries
- Lever
- Higher utilization
- Effect on cost/request
- Lower (fixed cost amortized)
- Effect on latency
- Risk of contention at the edge
- Tension
- Efficiency vs. headroom
| Lever | Effect on cost/request | Effect on latency | Tension |
|---|---|---|---|
| Larger batches | Lower (shared forward pass) | Higher (queue + bigger pass) | Throughput vs. responsiveness |
| Smaller / routed model | Lower for simple queries | Lower (less compute) | Quality vs. cost on hard queries |
| Higher utilization | Lower (fixed cost amortized) | Risk of contention at the edge | Efficiency vs. headroom |
Every cost win has a latency or quality cost attached - name the tradeoff, do not pretend it is free.
Latency is a distribution, not an averagethe tail is what users feel
An average hides the requests that actually hurt. If p50 is 40ms but p99 is 600ms, one in a hundred completions feels broken and a developer hits that tail many times an hour. Manage latency as percentiles and write SLAs against the tail.
- p50 (median)
- The typical experience; good for capacity math, useless as an SLA
- p95
- Where most SLAs live; the bad-but-common case
- p99 / p99.9
- The tail - rare per request, frequent across a day of use; this is what users remember
Batching that lifts throughput often fattens the tail - watch p99, not just the mean.
Model routingsend the easy work to the cheap model
Not every request deserves the biggest model. Model routing sends simple completions to a small, cheap, fast model and reserves the large model for genuinely hard queries. Done well it cuts cost and latency at the same time, because the small model is both cheaper to run and quicker to respond. The risk is misrouting: a hard query sent to the small model returns a weak answer, so the router's accuracy is itself a quality lever.
- 1Classify. A lightweight signal estimates query difficulty before committing GPU time.
- 2Route. Simple queries go to the small model; hard ones go to the large model.
- 3Measure. Track quality and cost per route, not just blended averages, so misrouting is visible.
- 4Tune. Shift the threshold as model capabilities and demand change - this is never set-and-forget.
Interactive diagram. Tab through its regions; each focused region shows its detail in the panel below.
Routing is a loop, not a switch - the measure step is the gate that catches misrouting before it ships.
Tab prediction needs to land inside a tens-of-milliseconds budget or the suggestion arrives after the developer's fingers have moved on. That budget tightly constrains both batching and routing: you cannot wait long to fill a batch and you cannot afford a slow large model on the hot path. So tab work tends toward small models, aggressive caching and minimal queueing, while heavier agent generations can tolerate more batching and routing. Naming this difference shows you connect serving mechanics to the actual product surface.
When asked "how would you lower cost per inference," do not name one lever. Walk the four together: route simple queries to a smaller model, batch where the latency budget allows, raise utilization on the committed fleet and verify the change against p95/p99 so you have not traded a cost win for a latency regression. Closing on the verification step is what separates a TPM from someone reciting tricks.
Takeaway. Cost per inference comes from model size, utilization, batching and routing together - and every cost win must be checked against the p95/p99 tail, never the average.
Self-check
QWhy track latency as a distribution rather than an average?
Utilization as the efficiency lever
After this you can treat utilization as the number you manage to.
GPUs in the wild commonly sit at 15-30% utilization. Closing the gap to 60-80% is the single largest efficiency program available to an infra TPM.
If a GPU costs the same idle or busy, then utilization is efficiency. The reason the number is usually low is rarely one big mistake - it is fragmentation, over-reservation and bursty demand each shaving off a slice. Your job is to make utilization a managed metric with a target band, not a thing people glance at after the fact.
Allocation utilization is how much capacity is reserved or assigned to teams. Compute utilization is how busy those GPUs actually are. A cluster can be 100% allocated and 20% busy - every card has an owner, almost none are working. The dangerous metric is allocation, because it looks full while the money leaks. Always ask which one a dashboard is showing.
The levers that raise itstandard moves, in order of usual payoff
Fit workloads onto fewer GPUs
Reduces stranded fractions of cards
Attacks allocation-vs-compute gap directly
Match capacity to demand over time
Shed idle hours in troughs
Bounded by GPU acquisition lead time
Run latency-tolerant batch on the same fleet
Backfills the gaps left by spiky inference
Needs isolation so it does not hurt the hot path
Failed work burns GPU time with zero output
Retry storms quietly destroy utilization
Track failure rate as a cost metric, not just reliability
That last card surprises people. A 10% failure-and-retry rate is not only a reliability problem - it means a tenth of your GPU-seconds produced nothing, then got spent again on the retry. Failed work is doubly expensive and it hides inside utilization that looks busy.
- Target band
- Set an explicit range (for example 60-80% compute utilization) per workload class
- Floor
- Below it, capacity is over-provisioned - shrink the reservation or co-locate
- Ceiling
- Above it, you have no headroom for burst - the next launch will be capacity-starved
- Cadence
- The recurring review enforces the band; a metric with no forum is a metric nobody manages
A band, not a single number - too low wastes money, too high removes safety margin.
Our fleet is 95% allocated but 28% busy, so the prize is the gap, not more cards. I would set a 65% compute-utilization target band per workload class, drive bin-packing and co-location to close it and make the weekly allocation review own the number. Below the band we shrink reservations; above it we add capacity ahead of the launch.
Takeaway. Manage to a compute-utilization band (not allocation, which looks full while money leaks) and treat failed-and-retried work as doubly expensive GPU-seconds.
Self-check
Capacity forecasting & demand modeling
After this you can tie GPU demand to product growth credibly.
A capacity forecast that starts from "how many GPUs do we want" is guessing. A credible one starts from product demand and derives the GPUs.
The chain runs from users to compute. Demand signals drive request volume, request volume and model choice drive GPU-seconds and GPU-seconds plus a utilization target drive the fleet size. Build it in that order and you can defend every number to ML and Finance, because each step is an assumption someone can challenge.
- 1Start from demand signals. DAU, requests per active user and the rollout schedule of new models and features - not a GPU count pulled from last quarter.
- 2Translate to compute. Map request volume and model/routing mix to GPU-seconds, stating the cost-per-request assumptions explicitly.
- 3Split baseline from peak. Model the steady reserve separately from burst; do not provision the whole fleet for the spikiest hour.
- 4Apply a utilization target. Divide required compute by the target band to get fleet size, so the plan bakes in efficiency.
- 5Run scenarios. Build base, upside and downside and pre-decide the trigger points that move you between them.
Interactive diagram. Tab through its regions; each focused region shows its detail in the panel below.
A credible forecast derives the fleet from demand - each step is an assumption ML or Finance can challenge.
Baseline vs. peakprovisioning for peak everywhere is how budgets blow up
- Component
- Steady baseline
- How you serve it
- Reserved / committed capacity
- Why
- Predictable, so capture the low per-hour rate
- Component
- Predictable peaks
- How you serve it
- Reserved sized to the band + scheduled scale
- Why
- Known shape, plan ahead of it
- Component
- Spiky burst & experiments
- How you serve it
- On-demand / serverless
- Why
- Absorb without stranding reserved spend
| Component | How you serve it | Why |
|---|---|---|
| Steady baseline | Reserved / committed capacity | Predictable, so capture the low per-hour rate |
| Predictable peaks | Reserved sized to the band + scheduled scale | Known shape, plan ahead of it |
| Spiky burst & experiments | On-demand / serverless | Absorb without stranding reserved spend |
Match the funding mode to the demand shape; reserving for peak everywhere strands capacity in the troughs.
Lead time and the cost of being wrongGPU supply is not instant
GPUs cannot be conjured on the day you need them. Supply is constrained and lead times are real, so a forecast has to run ahead of demand by the acquisition window or the plan is fiction. That lead time is exactly why scenario planning earns its keep: you pre-commit trigger points so you are ordering capacity before the upside case arrives, not after.
The discipline that makes a forecast trustworthy is quantifying the cost of being wrong in each direction. Over-provision and you strand reserved spend on idle cards. Under-provision and a launch is capacity-starved, degrading latency or blocking growth. Those costs are rarely symmetric and naming which way you are biased - and why - is what a senior leader is listening for.
- Over-provision
- Stranded reserved spend; the discount turns into idle hours you still pay for
- Under-provision
- Capacity-starved launch; latency SLAs break or growth is throttled
- The judgment call
- Decide which error is cheaper for this program, then size the buffer toward it on purpose
If the take-home or whiteboard asks you to forecast capacity, do not hand back one number. Hand back base/upside/downside with the assumptions visible, the baseline-vs-burst split, the lead time built in and an explicit statement of which direction you biased the buffer and why. A single point estimate signals you have never owned a forecast that got tested by reality.
Takeaway. Derive GPUs from demand (DAU → requests → GPU-seconds ÷ utilization target), split baseline from burst, build lead time in and state which way you biased the buffer.
Self-check
QWhy must a GPU capacity forecast run ahead of demand?
Running the allocation forum
After this you can design the recurring review that makes allocation decisions.
Capacity decisions are not made in a spreadsheet. They are made in a room where ML and Infra leaders trade off whose work gets the GPUs - and the TPM owns that room.
This is where the role's whole thesis lands: influence without authority. You do not get to assign GPUs by fiat and you should not want to. You build the framework, run the forum and own the data, so the decision is made on evidence by the people accountable for it. The final political call belongs to leadership; the quality of the call is yours.
- 1Stand up the cadence. A recurring allocation review with ML and Infra leadership and one named decision owner - not a committee that diffuses accountability.
- 2Require evidence to request. Every capacity ask brings current utilization, projected demand and expected value; no narrative-only requests.
- 3Make tradeoffs explicit. Funding one team's GPUs is declining another's - surface the opportunity cost in the room, do not let it stay implicit.
- 4Decide and record. The owner calls it; you log the decision and its rationale in a living ledger.
- 5Revisit on real data. Next cycle, check whether the granted capacity got used as promised and claw back what did not.
The bar to request capacityno evidence, no allocation
- Current utilization
- Are you using what you already have? Low utilization is a reason to deny, not grant
- Projected demand
- What signal drives the ask - DAU, a launch, an experiment - with numbers, not vibes
- Expected value
- What the capacity buys: revenue, a launch, a model improvement, a reliability fix
These three turn a request from advocacy into something the forum can compare across teams.
Interactive diagram. Tab through its regions; each focused region shows its detail in the panel below.
What carries a capacity request, ranked - current utilization is the gate the others never get past.
The capacity ledgerdecisions you can audit and revisit
Allocation drifts when grants are made and never revisited. A living capacity ledger records who got what, on what evidence and whether the bet paid off. It makes the forum self-correcting: a team that consistently under-uses its grant loses the argument next cycle on data, not politics. It also gives you the honest input for COGS attribution, because you can connect spend back to the team and product that asked for it.
- Who
- TPM (you)
- Owns what
- The framework, the forum cadence, the data and ledger, the explicit tradeoffs
- Who
- ML / Infra leadership
- Owns what
- The final allocation call and accountability for the outcome
- Who
- Requesting teams
- Owns what
- The evidence behind their ask and the utilization they promised
| Who | Owns what |
|---|---|
| TPM (you) | The framework, the forum cadence, the data and ledger, the explicit tradeoffs |
| ML / Infra leadership | The final allocation call and accountability for the outcome |
| Requesting teams | The evidence behind their ask and the utilization they promised |
You own the machinery of the decision, not the decision itself - that distinction is the role.
I would not try to own the allocation call - that belongs to the ML and Infra leads who are accountable for the outcome. I own the framework and the forum: a recurring review where every request shows current utilization, projected demand and expected value, where the opportunity cost of funding one team over another is on the table explicitly and where a living ledger lets us revisit grants on real usage. My job is to make the decision easy to get right.
Do not present the allocation forum as you deciding who wins. In a flat, founder-engaged, talent-dense org that reads as overreach and will sink you in the values round. The credible posture is that you make the tradeoffs legible and hold leaders to their commitments - you are the thought partner and the scorekeeper, not the referee handing out GPUs.
Takeaway. The TPM owns the framework, the forum and the capacity ledger - leadership owns the final call; every request shows utilization, demand and expected value or it does not get heard.
Self-check
QWhat does the TPM own in the allocation forum and what do they not own?