Cloud Cost Optimization and FinOps Questions
Controlling and optimizing cloud spend: cost modeling and forecasting, rightsizing, reserved capacity and savings plans, autoscaling for cost, tagging and chargeback, and the FinOps operating model. Covers building the business justification for infrastructure spend and continuously driving efficiency at scale without sacrificing reliability. Cost as a first-class architectural concern.
You need to decide between a managed autoscaling inference service and building your own Kubernetes-based inference platform with custom node pools. Build a cost model that includes the per-request or per-hour managed cost, the engineering and ops time you'd actually spend running it yourself, and the risk of downtime. What would tip the decision one way or the other?
Sample Answer
Direct answer
Build the total cost of ownership as the per-request or per-hour cost of the managed autoscaling inference service versus the fully loaded cost of a self-hosted Kubernetes-based platform, infrastructure plus the ops and engineering time to run it plus the expected cost of downtime, and compare them at your actual and projected request volume, not today's volume alone. In practice the deciding factor is rarely the sticker-price gap: it is whether you have, or can amortize, a platform team across enough services, and whether you face a hard requirement (custom hardware, strict latency, compliance) the managed option genuinely cannot meet.
Structured elaboration
1. Cost model components
- Managed: a per-request or per-hour unit price, plus a smaller ongoing ops full-time equivalent (FTE) for integration, monitoring, and continuous integration/continuous delivery (CI/CD), plus downtime risk that is typically low because the provider owns the service-level agreement (SLA).
- Self-hosted Kubernetes: the infrastructure cost of the node pools (compute-hours times an autoscaler-inefficiency overhead, since a self-managed cluster rarely packs at full utilization), plus a platform and site reliability engineer (SRE) FTE cost that is usually the dominant term at low-to-moderate volume, plus downtime risk that starts medium-to-high and falls as the platform matures.
2. Decision levers, roughly in the order they matter
- Volume: managed's linear per-request cost eventually crosses self-hosted's largely fixed cost; below that crossover, self-hosting is close to always more expensive.
- Team amortization: the platform-team FTE cost is fixed regardless of how many models it serves. One workload rarely justifies it; five or ten services sharing the same platform team change the math completely.
- Hard requirements: specialized accelerator hardware, latency below what the managed tier guarantees, or data-residency and compliance constraints the managed service cannot satisfy push you toward self-hosting regardless of the pure cost comparison.
- Time-to-market and current headcount: if you do not have more than one FTE to dedicate to platform work today, the true cost of self-hosting includes hiring or diverting that person, and the model should charge for that explicitly rather than treat it as free.
3. How to actually decide, not just estimate
- Build a multi-year monthly model for both paths, then run a short pilot, weeks rather than a quarter, at production-like traffic to replace assumed numbers (cold-start latency, real utilization) with measured ones.
- Track a monthly break-even: switch when cumulative self-hosted savings would exceed the platform build-out cost.
- Consider a hybrid split: managed for bursty or low-volume endpoints, self-hosted for the small number of high-throughput, latency-sensitive models where the fixed platform cost is easiest to justify.
Worked example
Assume a single inference service serving 20,000,000 requests/month.
Managed: $0.15 per 1,000 requests, plus 0.2 FTE of integration and monitoring work at $150,000/year fully loaded.
Managedannual=(100020,000,000)×$0.15×12+0.2×$150,000=$66,000
Self-hosted Kubernetes: 3 GPU-backed nodes at $2.50/hour, with a 1.2x autoscaler-inefficiency overhead, plus 1.5 FTE of platform and SRE time at $160,000/year fully loaded.
K8sannual=(3×$2.50×730×1.2)×12+1.5×$160,000=$318,840
| Managed | Self-hosted Kubernetes | |
|---|---|---|
| Infrastructure/month | $3,000 | $6,570 |
| Team cost/month | $2,500 (0.2 FTE) | $20,000 (1.5 FTE) |
| Total/year | $66,000 | $318,840 |
At this single-service volume, managed is nearly 5x cheaper ($66,000 vs $318,840/year), and the gap is almost entirely the platform FTE, not the infrastructure ($6,570/month infra vs $20,000/month people). Solving for the break-even monthly volume at these same unit prices gives roughly 160,000,000 requests/month, about 5,300,000/day, before the linear managed cost catches up to self-hosted's largely fixed cost. If the 1.5 FTE platform team is instead amortized across 10 services rather than dedicated to this one, the break-even drops to roughly 40,000,000 requests/month, about 1,300,000/day, still a high bar, which is why team amortization, not raw request volume alone, is usually the deciding lever.
Trade-offs and pitfalls
- Comparing infrastructure cost alone and ignoring the platform team: the FTE line is usually the dominant cost, and it does not shrink until it is shared across enough services.
- Treating downtime risk as free: a managed service's SLA has a real, usually low, expected cost; an immature self-hosted platform's downtime risk is real too and should be priced, not waved away.
- Building the platform before the hard requirement actually exists: if the stated driver is "we might need custom hardware someday," pilot on managed first and let a measured constraint force the migration.
- Ignoring autoscaler-inefficiency overhead: a self-hosted cluster's node pools rarely track demand as tightly as a request-billed managed service, and that slack is real spend.
- All-or-nothing framing: a hybrid split, managed for bursty or low-volume traffic and self-hosted only for the models that clear the break-even bar, often beats either pure strategy.
Compare reserved instances, savings plans, and committed-use discounts across the major cloud providers. What is the mechanical difference between them in commitment scope, term, and flexibility across instance types, and how would you decide what percentage of a steady-state workload's capacity to commit?
Sample Answer
Direct answer
All three mechanisms trade a usage commitment for a lower price, but they commit to different things: AWS Reserved Instances (RIs) commit to a specific instance configuration, AWS Savings Plans commit to a dollar-per-hour spend level that flexes across instance types, Google Cloud committed-use discounts (CUDs) commit to either a resource quantity or a dollar-per-hour spend depending on which CUD type you buy, and Azure Reservations commit to a specific VM configuration similar to AWS RIs. The general pattern across every provider is the same trade-off: the more precisely you commit to a specific instance shape, the bigger the discount; the more flexibility you keep, the smaller the discount but the lower your risk if the workload changes shape.
Structured elaboration
Mechanism comparison
| Mechanism | Provider | Commits to | Term | Flexibility |
|---|---|---|---|---|
| Standard Reserved Instance | AWS | Specific instance family, size, region | 1 or 3 yr | Least flexible: can change availability zone and, within limits, instance size in the same family, but not family or OS |
| Convertible Reserved Instance | AWS | Instance family (exchangeable) | 1 or 3 yr | Can exchange for a different family, size, or OS during the term, at a lower discount than Standard |
| Compute Savings Plan | AWS | Dollar-per-hour compute spend | 1 or 3 yr | Most flexible: applies across instance family, size, OS, tenancy, and region, and across EC2, Fargate, and Lambda |
| EC2 Instance Savings Plan | AWS | Dollar-per-hour spend, locked to one instance family and region | 1 or 3 yr | Flexible on size and OS within that family and region only; typically a larger discount than Compute Savings Plans for the same term because it's narrower |
| Resource-based CUD | Google Cloud | A quantity of vCPUs, memory, GPUs, or similar, on Compute Engine | Typically 1 or 3 yr | Locked to the committed resource type and quantity; scope can be a single project or shared across a billing account |
| Flexible (spend-based) CUD | Google Cloud | Dollar-per-hour spend | 1 or 3 yr | Pools eligible spend across only three services, Compute Engine, Google Kubernetes Engine (GKE), and Cloud Run, similar in spirit to an AWS Compute Savings Plan in that the discount follows a dollar-per-hour spend level rather than a specific SKU. BigQuery and Cloud SQL are NOT part of this pool: each has its own separate, service-specific spend-based commitment, purchased and applied independently |
| Reserved VM Instance | Azure | Specific VM series, size, and region | 1 or 3 yr | Instance-size flexibility within the same VM size-flexibility group; can be rescoped after purchase to a subscription, resource group, shared billing scope, or management group without a new commercial transaction |
All four providers offer some form of upfront, partial-upfront, or no-upfront (pay monthly) payment on these commitments at the same total cost, so the payment option is a cash-flow decision, not a discount-size decision on most of these products.
Why the scope difference matters in practice
A resource-level commitment (Standard RI, resource-based CUD, Azure Reservation) only pays off if the workload keeps needing that exact shape for the whole term; if the team migrates to a different instance family six months in, the commitment sits partially wasted (though AWS and Azure both allow some exchange or resale mechanisms to recover part of that). A spend-based commitment (Compute Savings Plan, flexible CUD) survives an instance-family change automatically, because the discount is applied to dollars spent on eligible usage, not to a specific SKU, at the cost of a somewhat smaller discount than the narrowest resource-level option.
Deciding what percentage of steady-state capacity to commit
Start from the floor, not the average: pull 3 to 6 months of utilization history for the workload, and find the usage level that held true on the worst week, not the typical week. That floor, not the mean, is the safe commitment baseline, because a commitment above the actual steady floor pays for idle capacity on every low-usage day. From there, the commitment size is a risk trade-off, not a fixed rule: a stable, mature workload with a long recent history of holding above that floor supports committing close to the full floor, while a workload still changing shape (recent re-architecture, aggressive growth, planned migration) justifies leaving more of the floor on-demand or covering it with a flexible, spend-based commitment instead of a rigid resource-level one, specifically because the risk being managed is "commitment outlives the workload's actual shape," not "commitment size in the abstract."
Worked example
A team's steady-state EC2 fleet held at a minimum of 40 instances of a given family over the last 4 months, with normal weekday peaks around 55 and occasional bursts to 70. The 40-instance floor is the commitment candidate, not the 55-instance average and not the 70-instance peak: committing at 55 would mean paying the commitment rate for capacity that isn't reliably used on quieter days, and any spike above 40 (up to and including the 70-instance bursts) is served by on-demand or spot capacity regardless of the commitment size. If this workload is expected to stay on the same instance family for the full term, an EC2 Instance Savings Plan or Standard RI sized to 40 instances captures the largest discount available on that stable floor; if a re-platforming project is likely to change instance family within the year, a Compute Savings Plan sized to the equivalent dollar-per-hour spend protects the same floor's discount while surviving the family change.
Trade-offs and pitfalls
The most common mistake is committing to the peak or the average instead of the floor, which either overpays for capacity that isn't reliably used or, worse, sizes a "safe" commitment so conservatively it captures almost none of the available discount. The second is choosing the narrowest, highest-discount resource-level commitment for a workload that's still changing shape, and then discovering the commitment doesn't match the new instance family, wasting real money for the rest of the term. The third, specific to the flexible/spend-based products, is assuming "flexible" means "no attention needed": a spend-based commitment still needs the underlying usage to stay above the committed dollar level, or the unused portion is still paid for and simply not applied to any usage.
Tell me about a time you found and eliminated a recurring source of cloud waste, like orphaned volumes or oversized instances. Walk me through how you found it, how you quantified the savings, and what you put in place to stop it from coming back.
Sample Answer
Direct answer
At a previous company I found and closed out a recurring waste pattern of orphaned storage volumes and oversized always-on instances: I built a script that cross-referenced billing data with resource metadata to quantify it, got stakeholder buy-in with a dollar figure and a grace period, then automated the fix so it stayed fixed instead of drifting back within a quarter.
Structured elaboration
Situation. Our monthly cloud bill kept creeping up even though we weren't adding meaningful new load. Two suspects stood out: unattached storage volumes left behind after instances were terminated, and general-purpose compute instances sized for peak load but running 24/7 at low utilization.
Task. I was asked to find the recurring waste, put a dollar figure on it, and put something in place so it didn't just come back in three months, since a couple of prior manual cleanups hadn't stuck.
Action.
- Joined the cloud billing export with resource metadata (attachment state, tags, and utilization metrics) to produce a weekly report of unattached storage volumes and instances running well below their provisioned capacity.
- Quantified the waste before touching anything: roughly 120 orphaned storage volumes (about 1.2 TB total) and 18 oversized instances, projected at about $4,500 a month in avoidable spend.
- Didn't delete anything unilaterally. I shared the report with the owning teams and finance, proposed a 7-day soft-delete window (snapshot first, then remove), and let owners object if a volume was intentionally kept around.
- Automated the fix rather than relying on the report catching it again: a scheduled job snapshots and tags volumes past a retention threshold, moves old snapshots to cheaper cold storage after 30 days, and a policy check flags newly-launched instances that don't match an approved size for their workload type.
- Documented the process as a runbook and added a recurring cost report to the team's chat channel so owners could see their own trend, not just a one-time cleanup event.
Worked example
The numbers, stated as I'd actually present them: 120 orphaned volumes and 18 oversized instances added up to about $4,500 a month, which is $54,000 a year ($4,500 times 12). We recovered more than 95% of that within two weeks of the soft-delete window closing, with zero service incidents (the soft-delete window is exactly what caught the handful of volumes someone still needed). The automation meant the next quarterly audit found near-zero recurrence in the same category, versus the pattern repeating every few months before.
Trade-offs and pitfalls
- The soft-delete window is the part people skip under time pressure, and it's the part that prevents an incident. Immediate hard deletes are faster but one mistaken deletion of a volume someone forgot to tag correctly turns a cost win into an outage.
- A one-time cleanup without automation is a recurring line item on someone's calendar, not a fix. The automation (or a policy gate at provisioning time) is what actually stops the waste from returning; the cleanup itself is just catching up on the backlog.
- Quantifying savings from projected monthly rate rather than realized post-cleanup spend risks overstating the win if some of those instances were legitimately needed and get resized back up. Track the actual bill delta in the following cycle, not just the projected figure.
- The same pattern (orphaned storage, oversized always-on compute) shows up in machine learning infrastructure too, often as idle GPU-backed training instances left running between experiments or oversized inference endpoints sized for a launch-day spike that never sustained; the detection and automation approach is the same, just pointed at a different resource class.
What are spot or preemptible instances, and what makes a workload a good fit versus a bad fit for them? What are the typical interruption modes, and what simple engineering strategies would a team use to mitigate them?
Sample Answer
Direct answer
Spot instances (called preemptible VMs on Google Cloud) are spare cloud compute capacity sold at a steep discount to on-demand pricing, with one condition attached: the provider can reclaim the instance on short notice whenever it needs that capacity back. A good-fit workload is horizontally scalable and tolerant of a node disappearing mid-task; a bad-fit workload is a single-node stateful service that can't lose in-flight state without real damage. The engineering mitigations are all versions of the same idea: assume interruption will happen and make it cheap when it does.
Structured elaboration
What makes a workload a good fit
Stateless or checkpointable, horizontally scalable, and able to tolerate a node vanishing without warning. Batch processing, distributed data jobs, CI/CD workers, autoscaled stateless services behind a load balancer, and ML training with periodic checkpointing all fit this pattern well, because losing one worker just means that worker's unit of work gets retried elsewhere.
What makes a workload a bad fit
Anything where a single node holds state that isn't replicated or persisted elsewhere: a standalone database, a service relying on sticky sessions with in-memory state, or any long-running job with no checkpointing where losing the instance means losing all progress made so far. Latency-sensitive, user-facing services with a strict availability SLA are also a poor fit unless they're built with enough redundancy to absorb losing a fraction of their capacity at any moment without a visible dip.
Typical interruption modes
The provider sends a termination notice with a short window, commonly on the order of one to two minutes, before reclaiming the instance. In that window the instance can be forcibly stopped or terminated depending on configuration, and any data on local (non-persistent) storage is lost unless it was written somewhere durable first. The instance's local IP address and any unsaved in-memory state disappear with it.
Engineering strategies to mitigate interruption
- Checkpoint frequently and keep work units small: persist progress to durable storage (object storage, a database) often enough that losing an instance only costs the work done since the last checkpoint, not the whole job.
- Listen for the termination notice and drain gracefully: stop accepting new work, finish or checkpoint in-flight work, and deregister from the load balancer or work queue within the notice window so in-flight requests aren't dropped mid-response.
- Mix capacity types: run a pool blending spot and on-demand (or reserved) instances, so a wave of simultaneous spot interruptions doesn't take the whole service down, and configure autoscaling to backfill with on-demand capacity when spot availability drops.
Worked example
A batch video-transcoding job processes 10,000 clips and normally runs on 20 on-demand workers at an illustrative rate of $0.40/hour each, or $8.00/hour in aggregate compute cost, taking roughly 5 hours to clear the queue, for a total of $40 in compute.
Moving to spot capacity at an illustrative $0.12/hour per worker (a 70% discount to the $0.40 on-demand rate used above) cuts the hourly rate to $2.40 for the same 20 workers. Assume, based on the provider's historical interruption rate for this instance type, that 15% of worker-hours are lost to interruption and have to be redone. The effective compute time becomes 5 hours ÷ (1 − 0.15) ≈ 5.9 hours, so total spot compute cost is:
$2.40/hr×5.9 hr≈$14.16against $40.00 on-demand, a savings of roughly 65% after accounting for rework, even though the raw hourly discount was 70%. The gap between the 70% sticker discount and the 65% realized saving is exactly the cost of the interruption overhead, and it's why checkpointing (which shrinks how much work is actually lost per interruption) matters more to the real savings number than the headline discount does.
Trade-offs and pitfalls
The most common mistake is moving a workload to spot without first confirming it's actually checkpointable or replaceable, which turns an interruption from "retry a small unit of work" into "lose hours of progress" and can wipe out the savings entirely. A second is ignoring capacity availability: spot capacity for a specific instance type in a specific zone can simply run out, so a design that hard-depends on one instance type in one zone will stall, not just run at reduced discount; diversifying across instance types and zones is what actually protects availability, not just cost. A third is treating the interruption notice window as guaranteed processing time for a graceful shutdown that takes longer than the notice allows; if draining in-flight work genuinely takes longer than the notice period, the workload needs idempotent retry logic downstream, not just a shutdown handler.
Your monthly cloud bill is $500,000, you served 1 billion requests, and you stored 10,000 TB-months of data. Walk through how you would compute cost per request and cost per TB-month, what assumptions you would need to split compute, storage, and egress, and how you would present these numbers to a non-technical product manager.
Sample Answer
Direct answer
Don't just divide the whole bill by requests, that blended number mixes together costs that behave completely differently. Split the bill into the categories that actually scale with request volume (compute, egress) versus the one that scales with data volume (storage), using real per-service billing line items if you have them or a clearly stated percentage assumption if you don't, then divide each category by its own denominator. State the assumption explicitly wherever real billing data isn't available, since a non-technical stakeholder needs to know which numbers are facts and which are estimates that could be wrong.
Structured elaboration
- Compute the naive, blended metric first, as an anchor, not an answer. It's the cheapest number to produce and useful for a sanity check, but it hides which lever actually matters.
- Get real per-service billing line items if the cloud provider's billing export supports it. Most providers can break a bill down by service (compute, storage, network) directly; that data should always replace an assumption once it's available.
- If you can't get real line items yet, state a percentage split explicitly based on what you know about the workload, and flag it clearly as an assumption a reviewer could challenge, not a fact.
- Divide each category by the metric it actually scales with: compute and egress by request count, storage by TB-months (terabyte-months).
- Show sensitivity. Because the split is an assumption, show how the resulting unit cost moves if the assumption is wrong, so the reader understands the number's precision isn't higher than it really is.
- Present it as one dominant number plus the assumption, not five numbers. A non-technical product manager needs "here's our cost per request, and here's what we assumed to get there," not a full cost-accounting breakdown.
Worked example
Naive, blended metric:
CostPerRequest=1,000,000,000500,000=$0.0005
CostPerTBMonth=10,000500,000=$50 per TB-month
Reasoned split (stated explicitly as an assumption): compute 50%, egress 30%, storage 20% of the bill.
StorageDollars=0.20×500,000=$100,000,10,000$100,000=$10 per TB-month
ComputeEgressDollars=0.80×500,000=$400,000,1,000,000,000$400,000=$0.0004 per request
Sensitivity check: if compute alone were 60% of the bill instead of 50% (with egress absorbing the 10-point difference):
Baseline (50% compute):0.50×500,000=$250,000,1,000,000,000$250,000=$0.00025 per request
Scenario (60% compute):0.60×500,000=$300,000,1,000,000,000$300,000=$0.0003 per request
That's a 20% shift in the compute-only unit number from a 10-percentage-point shift in the assumption. That's the point to make to the product manager: the unit cost is real, but its precision is bounded by how confident you are in the split.
Why the number improves with scale (if part of the bill is fixed capacity): if F is the portion of spend that's fixed regardless of volume (reserved capacity, base storage commitments) and v is the variable cost per request, then
CostPerRequest(N)=NF+v
As request volume N grows, the fixed-cost term shrinks and cost per request drifts down toward v, the pure variable rate. This is a directional insight, not a specific forecast, because the actual fixed/variable split for this bill would need to come from the real billing line items in step 2.
Trade-offs and pitfalls
- The blended number hides which lever matters. If egress is actually 60% of this bill rather than the assumed 30%, an optimization effort aimed at compute would be attacking the wrong target entirely.
- Presenting false precision to a non-technical stakeholder invites a question you can't answer. If the cost-per-request figure moves 20% next month purely because the underlying assumption shifted, and that assumption was never stated, the PM (product manager) has no way to know whether that's a real change or measurement noise.
- Ignoring committed or reserved spend in the mix misattributes savings. If part of the $500k is a reserved-capacity commitment, its benefit shouldn't get credited only to whichever service happens to run heaviest that particular month.
- A per-customer breakdown uses the same math, just a finer grain. If you needed cost per customer instead of an aggregate, the same category split applies per customer using the same allocation logic against each customer's metered usage (requests, storage, egress) joined to the billing export, typically expressed as a grouped aggregation over the usage data rather than a fundamentally different calculation.
Unlock Full Question Bank
Get access to all 7 Cloud Cost Optimization and FinOps interview questions and detailed answers.
Sign in to ContinueJoin thousands of developers preparing for their dream job.