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.
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.
Define Total Cost of Ownership for a cloud migration. What cost components would you include when comparing an on-premises deployment to public cloud, including the one-time, ongoing, and easy-to-forget hidden costs, and how does the shift from capex to opex change how this gets reported to finance?
Sample Answer
Direct answer
Total cost of ownership (TCO) for a cloud migration is the full cost of moving to and running on the cloud over a fixed horizon, typically 3 to 5 years, not just the sticker price of the compute and storage you provision. It has to include one-time migration costs, ongoing operational costs, and a set of hidden costs that are easy to leave out of the first draft. Underneath the cost model sits an accounting shift that changes how finance evaluates the whole decision: on-premises infrastructure is largely capital expenditure (capex), paid upfront and depreciated over years on the balance sheet, while cloud spend is operating expenditure (opex), an ongoing monthly cost that hits the income statement as it's incurred, and that shift changes who approves the spend and how it's reported, independent of whether the total dollar amount is higher or lower.
Structured elaboration
One-time migration costs
Assessment and planning, re-architecting or refactoring applications that don't lift-and-shift cleanly, the data migration itself (transfer tooling, bandwidth, and often a real egress charge for the initial bulk move), landing-zone setup (networking, identity, security baseline), and the cutover and validation window, including the cost of any parallel-running period or rollback plan if the migration doesn't go cleanly.
Ongoing operational costs
Compute, storage, and networking at whatever mix of on-demand and committed pricing the workload ends up using; managed services (databases, messaging, CDN) priced per-use rather than as a fixed asset; the operations and SRE (site reliability engineering) staffing needed to run the environment, including on-call load, which doesn't disappear just because infrastructure moved to a managed platform; backup, disaster recovery, and monitoring tooling; and provider support-tier contracts.
Hidden and easy-to-forget costs
Software licensing terms often change under cloud deployment (per-core on-prem licensing doesn't always map cleanly to per-vCPU cloud pricing, and some vendors charge a premium for cloud deployment specifically). Team training and the productivity dip while staff ramp on new tooling is real money even though it never appears on a cloud invoice. Data egress charges recur beyond the initial migration if the architecture routinely moves data out of the cloud provider's network. And the performance-tuning and cost-optimization cycles that follow a migration (the first few months of "why is this more expensive than we modeled" work) are themselves an ongoing cost, not a one-time true-up.
The capex to opex shift, and why it changes the finance conversation
On-premises hardware is typically capitalized: bought upfront, placed on the balance sheet as an asset, and depreciated over its useful life, so the income-statement impact in any given year is just that year's depreciation, not the full purchase price. Cloud spend is usually opex: an ongoing operating cost that lowers reported profit in the period it's incurred, in full, the same way a utility bill does. This changes three things finance cares about independent of whether the total spend is higher or lower: the approval process (a large capex purchase typically needs a one-time capital-budget approval, while opex is a recurring line item reviewed every budget cycle, which can mean more frequent scrutiny), the reported financial metrics (heavy capex improves near-term reported profit relative to opex of the same economic cost, because depreciation spreads the hit over years), and the predictability of the number finance has to plan around (a capex purchase is a known fixed cost for its depreciation life; cloud opex scales with usage and can vary month to month, which is exactly why a TCO model with clear assumptions matters to the finance stakeholders reading it).
Assumptions to document alongside the number
State the time horizon and any discount rate used, the utilization and growth assumptions behind the ongoing-cost estimate, how each on-prem resource maps to a cloud instance type or managed-service tier, the pricing model assumed (on-demand vs. committed), and a confidence level per line item, since the migration and hidden-cost categories are usually far less certain than the ongoing compute estimate.
Worked example
A company is comparing a 3-year on-prem refresh against a 3-year cloud migration for one application. On-prem: a $600,000 hardware refresh (capex, depreciated straight-line over 3 years, so $200,000/year hits the income statement) plus $90,000/year in colocation, power, and ops staffing (opex), for a 3-year total cash outlay of $600,000 + $270,000 = $870,000, though the year-1 income-statement impact is only $200,000 (depreciation) + $90,000 (opex) = $290,000. Cloud: $40,000 in one-time migration cost, plus $220,000/year in compute, storage, managed database, and reduced ops staffing (opex throughout), for a 3-year total of $40,000 + $660,000 = $700,000, all recognized as opex in the year incurred.
TCOon-prem, 3yr=$600,000+(3×$90,000)=$870,000 TCOcloud, 3yr=$40,000+(3×$220,000)=$700,000Cloud is $170,000 cheaper over 3 years on total cost, but a finance team focused only on year-1 reported profit sees on-prem hit the income statement for $290,000 in year 1 versus cloud's $260,000 (the $40,000 migration cost plus $220,000 opex), a smaller gap than the 3-year total suggests, and by year 3 on-prem's income-statement hit is $200,000 (depreciation) + $90,000 (opex) = $290,000 again while cloud stays at $220,000. Presenting only the 3-year total TCO to a finance stakeholder who evaluates budgets year by year misses that the two options have a genuinely different shape over time, not just a different total.
Trade-offs and pitfalls
The most common mistake is comparing cloud opex against only the visible on-prem opex (power, colocation) while forgetting that the on-prem hardware's capex has a real, if deferred, cost through depreciation, which understates the true on-prem TCO. The second is presenting a single TCO number to finance without the capex-versus-opex framing, which leads to a confusing conversation when the "cheaper" option somehow needs a harder budget approval, because it's asking for a new recurring opex line instead of a one-time capital purchase finance may already have approved. The third is treating the migration-cost and hidden-cost categories with the same confidence as the ongoing-cost estimate; they are consistently the most underestimated part of a cloud TCO model, and should be flagged with a lower confidence level and a sensitivity range, not presented as a single precise figure.
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.
You need to forecast next quarter's cloud spend from 12 months of history that trends upward with some seasonality. Outline a simple forecasting approach you could stand up quickly, how you'd communicate the uncertainty in that forecast to stakeholders, and what would make you reach for a more sophisticated model.
Sample Answer
Direct answer
For a quick, stand-up-able forecast I'd fit a simple linear trend to the 12 months of history, extend it three months for next quarter, and wrap it in a prediction band from the regression's own residual error rather than presenting a single point number. I'd reach for a more sophisticated model only once I have evidence the simple one is systematically wrong, not preemptively.
Structured elaboration
The quick approach:
- Plot the 12 months first. Confirm it's a genuine upward trend and note anything that looks like a repeating spike versus a one-off (a migration, a pricing change, a one-time reserved-capacity purchase).
- Fit an ordinary least squares line, spend as a function of month index. This is one formula in a spreadsheet or a few lines of code, and every stakeholder can sanity-check a straight line on a chart.
- Extend that line three months forward for the next quarter's point forecast.
- Compute the regression's residual standard error (how far actual spend typically sits from the fitted line) and present a band around the point forecast, not just a single number.
Communicating uncertainty to stakeholders:
- Lead with the point forecast, then the band, then the assumption it rests on: "roughly $X, plus or minus $Y, assuming the current growth rate holds and no new large purchases land."
- Show the band as a range on the same chart as the historical trend line, not as a separate table of numbers. A visual band reads faster than a confidence-interval sentence.
- Name the one or two things most likely to break the forecast explicitly (a known upcoming launch, a planned migration) rather than letting the model silently assume none of that happens.
When to reach for something more sophisticated:
- Only one cycle of history. With exactly 12 months you have one observation per calendar month, so you can visually spot a repeating pattern (say, a December spike) but you cannot statistically validate it's seasonal rather than a one-off; flag it as a risk, don't build a seasonal model on a sample size of one.
- A structural break. A step change from a contract renegotiation, a major re-architecture, or a large one-time purchase breaks the "one consistent trend" assumption the line depends on; segment the data around the break instead of fitting through it.
- Residuals that don't look like noise. If the gaps between actual and fitted spend show their own pattern (consistently growing, or consistently high in the same months) rather than scattering randomly, the straight line is missing something systematic, which is the signal to try a model built for trend plus seasonality (methods like ARIMA, ETS, an exponential-smoothing state-space model, or Prophet) once there's enough history (typically 24+ months) to fit one reliably.
Worked example
Twelve months of cloud spend, in thousands of dollars: 95, 98, 101, 103, 108, 106, 110, 113, 111, 116, 119, 134 (months 1 through 12, December is month 12).
Fitting the line by hand: mean month = 6.5, mean spend = $109.5k. The slope and intercept come out to:
b=2.734,a=91.727So the fitted line is spend ≈ 91.7 + 2.73 × month. Extending three months for next quarter (months 13, 14, 15):
y^13=127.3,y^14=130.0,y^15=132.7 ($k)That's a next-quarter total point forecast of about $390k. The residuals (actual minus fitted) range from about -5 to +9.5, with month 12 (December) sitting about 7.6% above the trend line, the one visible spike. The residual standard error works out to roughly $3.9k, so a rough band using two standard errors is:
y^t±2⋅SEresid,SEresid≈3.9giving a next-quarter total range of roughly $367k to $413k. I'd present that as "about $390k, likely between $367k and $413k, assuming December's spike doesn't repeat as a new baseline level and no major new workloads launch." If a second December came in with a similar spike, that's the trigger to stop treating it as noise and start modeling it as real seasonality.
Trade-offs and pitfalls
- A single point forecast without a band invites stakeholders to hold you to a number that was never that precise. The band is not optional decoration, it's the honest version of the answer.
- Extrapolating a linear trend blindly past the range you fit it on gets worse the further out you go; three months past twelve months of history is reasonable, forecasting a full year out on the same line is not.
- The common wrong turn is reaching for a complex model (multiple seasonal cycles, machine-learning regressors) before the simple model has actually failed. Complexity should be earned by evidence of a problem, not applied by default because it sounds more rigorous.
- Treating one visible spike as proven seasonality with only one year of history is the specific trap worth naming out loud to stakeholders, since it's an easy way to overfit a forecast to a single event.
How would you set up a basic cost anomaly detection system that alerts when a team's weekly spend deviates materially from normal? What data sources and metrics would you ingest, what's a simple first detection rule, and how would you avoid drowning the team in noisy alerts?
Sample Answer
Direct answer
A basic weekly cost anomaly detector needs three things: daily billing data broken down by team and service, a simple statistical baseline (a rolling median works better than a rolling average for this), and a threshold that requires both a large percentage move and a large absolute dollar move before it pages anyone, so a small team's routine variance doesn't generate the same alert as a large team's genuine spike.
Structured elaboration
Data sources and metrics to ingest:
- Daily billing line items from the cloud provider's cost and usage data, not monthly, since daily granularity is what lets you catch a spike before the invoice lands.
- Tag or label mappings so every dollar of spend attributes cleanly to a team, project, and environment. Without reliable tagging, "which team's spend spiked" becomes a manual investigation instead of an automated alert.
- A calendar of known events (planned migrations, release windows, seasonal traffic events) so the detector can tell "we deliberately scaled up" apart from "something is wrong."
A simple first detection rule:
- Compute each team's total spend for the current week.
- Maintain a rolling baseline: the median of that team's weekly spend over the past 8 to 12 weeks. Median rather than mean matters here because a single earlier spike shouldn't drag the baseline up and make the detector blind to a second one.
- Compute the percentage deviation from that baseline.
- Flag an anomaly only if the deviation exceeds a percentage threshold (for example, 50%) and the absolute dollar change exceeds a minimum floor (for example, $1,000). Requiring both conditions is what keeps a team with a $200 baseline from generating the same noisy alert as a team with a $2 million baseline moving by the same percentage.
Keeping the team from drowning in noise:
- Use a robust spread measure like the median absolute deviation instead of standard deviation to size the threshold, since a handful of past outliers otherwise widen the "normal" band and make the detector less sensitive exactly when it should be more sensitive.
- Require the deviation to persist for more than a single day before alerting on a weekly view, so a one-day billing artifact (a delayed invoice line landing all at once) doesn't trigger a page.
- Suppress alerts during a known, calendar-declared event (a planned migration, a load test) rather than making every planned cost increase look identical to an unplanned one.
- Let the team that receives an alert mark it as a false positive, and feed that back into tuning the threshold. A detector that's never allowed to be wrong in a documented way just gets muted instead.
- Tier the alerts: a moderate deviation goes to a low-urgency channel (a message, not a page), and only the largest, most sustained deviations page someone directly.
Worked example
A team's baseline (median of the last 10 weeks) is $8,000 a week. This week they spend $13,500. The deviation is (13,500−8,000)/8,000=68.75%, which clears the 50% threshold, and the absolute change is $5,500, which clears the $1,000 floor, so this fires as an anomaly. Compare that to a small team with an $800 baseline that spends $1,300 this week: the deviation is also over 50% (62.5%), but the absolute change is only $500, below the floor, so it doesn't page anyone, it just shows up on the weekly dashboard for someone to glance at when convenient. That's the point of the two-condition rule: it protects small teams from noisy pages while still surfacing genuinely large moves.
Trade-offs and pitfalls
- A percentage-only threshold looks reasonable until you apply it to a team with a tiny baseline, where normal week-to-week noise routinely exceeds 50%. The dollar floor is what prevents that class of false positive, and it's easy to forget when first designing the rule.
- A rolling average baseline (instead of median) means one real spike stays baked into "normal" for weeks afterward, quietly raising the bar for detecting the next one. This is a common and subtle mistake worth catching in review.
- Daily granularity catches problems faster than weekly but is noisier; weekly smooths noise but means you find out up to six days later. A reasonable middle ground is a daily check against a weekly baseline, which is what the worked example above effectively does.
- The detector is only as good as tag coverage. If a meaningful share of spend is untagged or mis-tagged, anomalies in that bucket are invisible to a team-scoped detector, which is itself worth surfacing as its own metric to track down separately.
Unlock Full Question Bank
Get access to all 11 Cloud Cost Optimization and FinOps interview questions and detailed answers.
Sign in to ContinueJoin thousands of developers preparing for their dream job.