Skip to content

Commitment coverage

Steady, predictable usage that runs on on-demand pricing is leaving a discount on the table. Reservations, Savings Plans, and committed-use discounts trade a term commitment for a lower rate. The risk is the mirror image: a commitment you over-buy, under-use, or scope too narrowly wastes money instead of saving it.

  • Coverage gaps: a steady baseline of on-demand spend on a family/region that a commitment would cover, sized from your real usage history with a modelled payback and waste-risk.
  • Under-utilized commitments: reservations or plans you already hold that aren’t being fully consumed, where returning the idle quantity or a scope change recovers value. An exchange cannot shrink a reservation (the new one must commit at least what the old one had left), so it only helps when there is on-demand capacity to move into it.
  • Expiring soon / scope mismatch: coverage about to lapse, or scoped so narrowly it can’t apply where the usage actually is.

Every recommendation carries the coverage percent, the monthly commit, the break-even month, and the modelled waste risk, so finance can sign off on the term, not just the headline saving.

A reservation only pays off on capacity that runs every hour of its term, and Azure does not sell one for every size. So each Azure recommendation is built from two facts, never from a flat discount:

  • What ran every day. We count only the machines that ran every day of the last 30 days, measured from the daily usage hours on your own bill. A machine scheduled off at night, or a short-lived job node, does not back a three-year purchase. A day we have no usage hours for proves nothing, so a machine only counts once its whole window is measured.
  • Azure’s own rate for that exact size. Each machine is priced at the reservation or savings-plan rate Azure publishes for its size, region and operating system. A size with no reservation to buy earns none (it may still earn its savings-plan rate), and a Windows machine earns the discount on its compute only, because the Windows licence keeps billing at pay-as-you-go.

A reservation is bought in one region, so a family that runs in two regions gets one reservation recommendation per region. We also leave out machines another recommendation already says to stop, schedule or resize, net out reservations you bought after the window started, and never recommend more instances than Microsoft’s own reservation recommendation for the same subscription, size and region. If you negotiated a different commitment discount, set it under Admin → Cost model; it replaces Azure’s rate on the sizes Azure sells that commitment for.

Eligible spend covered is your covered spend divided by covered plus on-demand, over the latest complete billing month. The current month is excluded on purpose: a few days of spend reads as a near-zero month and would make the ratio unexplainable.

Each cloud is measured on its own. You see one figure per cloud you have connected, never added together: the clouds sell different commitments, count “covered” differently and close their months on different days.

  • AWS counts the usage a Savings Plan or reservation can cover (EC2 instance hours, Fargate, Lambda, and the instance hours of RDS, ElastiCache, OpenSearch and the other database engines) at on-demand (list) prices, which is how AWS’s own coverage report counts. NAT, data transfer, storage and other usage a commitment cannot cover are left out and shown as spend we did not confirm. An AWS account without a Cost and Usage Report is measured from Cost Explorer instead: EC2, RDS, ElastiCache and Redshift running hours at billed cost, which reads lower than AWS’s own report.
  • GCP counts the Compute Engine, Cloud SQL, Cloud Run and Autopilot usage a committed use discount covers, at list prices once your billing export carries them. Until then it is measured at billed cost, and the panel says so.
  • Azure counts the services Azure sells a reservation for, at billed cost, as described below.

At billed cost a covered hour counts at its discounted price, so the figure reads lower than the provider’s own coverage report. The panel names the basis next to every figure.

On Azure, the denominator is not your whole bill: it is the spend Azure actually sells a commitment for:

  • Virtual Machines (Compute)
  • App Service
  • Azure Kubernetes Service
  • Container Instances
  • SQL Database, on its vCore meters: vCore and Zone Redundancy vCore, the two meters Azure publishes a reservation price for.
  • Azure Database for PostgreSQL and Azure Database for MySQL, on their vCore compute meters. Azure publishes 1,600 PostgreSQL and 374 MySQL reservation prices and every one of them is on a single meter name, vCore, across General Purpose and Memory Optimized compute. Burstable (B-series) database compute has no reservation to buy at all, so it is not part of the denominator.

Three kinds of spend are held out of the denominator. The Coverage by family panel names each one with its amount, so you can see exactly what the percentage does not speak for:

  • Spot: spot capacity cannot be reserved. Counting it would depress your coverage permanently and falsely.
  • Rows your bill carries no pricing model for: an unattributed row is not evidence of on-demand, so it is never folded in as uncovered.
  • Database meters we have not confirmed reservable: DTU-model SQL databases, burstable PostgreSQL/MySQL compute, storage, backup, IO, and the Extended Support surcharge. Azure publishes no reservation price for them, so a DTU or burstable database is not an uncovered gap you can close; it is a different purchase model. The panel names the services this applies to and the amount, so nothing is dropped silently.

That last split is exact: across every Azure tenant we measured on 2026-08-14, each non-vCore SQL meter on the July bill is a DTU tier (10 DTUs, eDTUs, S3 DTUs, B DTU, …) or a storage/backup meter (General Purpose Data Stored, LRS Data Stored, Backup RA-GRS Data Stored, …), separable by name with no judgement call. The same held on 2026-08-23 for the two Azure Database families.

The size of that split is not cosmetic. On one production tenant’s July bill, counting the whole PostgreSQL service would have read 11.1% covered against a $601.35 denominator. Counting only what Azure sells a reservation for reads 26.5% covered against $252.03: the difference is $241.99 of burstable compute plus $107 of storage and backup that no reservation can touch. The same tenant’s MySQL spend that month is entirely IO, burstable and storage, so MySQL shows no coverage bar at all rather than a “0% covered” figure you could not act on.

Azure bills several non-reservable products on the same vCore meter as the reservable ones, so the meter alone cannot answer “could this have been reserved”. Two are large on a real SQL Database bill: serverless compute, and the SQL licence, which a reserved-capacity purchase never covers (it buys compute; only Azure Hybrid Benefit removes the licence). On one production subscription’s July 2026 bill the licence leg was 8,532.38 of roughly 17,075 of vCore spend: half that subscription’s denominator.

Since 2026-08-23 we read a second signal from your bill, Azure’s meter subcategory, which names the product group inside the meter (Single/Elastic Pool General Purpose - Compute Gen5 vs … - SQL License). Product groups we have measured as non-reservable come out of the SQL bar and are reported as not confirmed reservable, alongside the DTU and storage meters. Serverless compute and the SQL licence are the two that matter today.

We only take out what we have measured. A product group we have not catalogued keeps counting toward the denominator, and so does spend billed before we started reading the subcategory. That is a deliberate choice about which way to be wrong:

  • Counting something non-reservable makes your covered share look worse than it is. You investigate a gap that is smaller than advertised.
  • Dropping something reservable would make it look better than it is, and telling you that you are protected when you are not is the one error we will not ship.

So your coverage percent is that figure or better, never worse, on every family. The part driven by pre-2026-08-23 rows self-heals as newer months are ingested.

One thing we never do in either direction: drop spend your bill shows was actually billed under a reservation or savings plan. If Azure applied a commitment to the row, the product is reservable by definition and it stays in both halves of the ratio.

Azure Database for PostgreSQL and MySQL work the same way. Nothing is taken out of them on subcategory yet (we have not measured a non-reservable product on their vCore meters), so those bars behave exactly as they did before, in the same safe direction. Burstable compute never reaches that test at all: it bills on its own B1MS meter, so the meter list already excludes it. Azure Cosmos DB for PostgreSQL (Citus) compute is reservable and bills under the PostgreSQL service name, and it simply counts, which is where reservable spend belongs.

Commitments that discount spend, not resources

Section titled “Commitments that discount spend, not resources”

Google’s Flexible and Cloud SQL committed-use discounts commit a dollar amount per hour rather than a named machine. The fee arrives as a separate line that is offset by the spend you actually consumed. The covered usage bills at the discounted price and names the commitment in the export’s consumption model, so we count it as covered; older months billed before Google moved to that model carry no such mark.

Where you hold one of these and a service still measures 0% covered (those older months), the by-service bar on the Costs page reads “committed” instead of a coverage percentage, a literal “0% covered” would deny a commitment you are paying for. Any other percentage on that service is shown with a ≥: it is a floor, because usage from before the model change cannot be counted as covered.

Drill into the service and its Commitment coverage split says the same thing in a footnote: “A spend-based commitment is active on Compute Engine. Its discount is billed as a fee split, not a per-line credit, so the percentage above cannot include it.” The split itself is untouched, no invented segment, no nudged percentage. The chart keeps showing only what your bill actually attributes; the sentence tells you what it therefore leaves out.

The per-tag coverage drawer says nothing about spend-based commitments, and hides nothing either. A tag value spans many services, so “does this commitment cover this tag?” has no answer we could defend at that grain, so we show you the same attributed percentage as everyone else rather than annotate it with a guess.

The number that is measurable sits on the Commitments page: how much of the committed spend the closed month absorbed, and how much you paid for and did not use. That utilization is read from your bill, not modelled.

Two consequences worth knowing:

  • We read these commitments from your billing export, because Google’s commitments API does not list them. If the export starts before the commitment was bought, we can date it; if the commitment predates your export entirely, we leave it out rather than guess a purchase date and term.
  • We only ever measure closed billing months. Mid-month, the fee and its offset arrive out of step and the utilization would read as nonsense.

While such a commitment still has unused headroom, we will not recommend buying another one for the same service: those dollars are already committed. Filling the commitment you have is the cheaper move.

Sizing reads your billing history. History cannot see a decision you have already made: a server you are decommissioning next spring, a project winding down, a migration that ends in eighteen months. That spend is in every month we look at, so it lands in the baseline at full weight, and a three-year purchase gets sized on money you will stop spending.

If you already know a workload is leaving, mark it and we size the term around it. Open a recommendation, find the resource in the spend-ranked list inside it, and give it an expected end month with a reason. From then on:

  • A three-year purchase stops counting spend that ends in eighteen months.
  • A one-year purchase still counts it, because it survives that term. The same resource can make a shorter commitment the better buy, and often does.
  • Every term shows its own baseline, so you can see exactly what was set aside and how much the commitment actually moved.

Marking is reversible, records who made the call and why, and is blocked on a recommendation you have already accepted: the purchase paperwork is written by then, and it should not disagree with the engine.

When we withhold a purchase recommendation entirely

Section titled “When we withhold a purchase recommendation entirely”

Marking a workload as leaving is one way we learn a baseline won’t hold. The other is the trend itself: when a family’s spend has fallen sharply against its own recent average (even without anything marked), sizing a one- or three-year purchase on it would commit you to money that is already gone. We withhold the affected term rather than print a “buy” recommendation next to a waste-risk number that is really telling you the same thing.

  • We check each term (one-year, three-year) against its own recent trend, so a shorter commitment can still go ahead even when a longer one is withheld.
  • If marking a resource as leaving fully explains the drop, the term is sized on what survives instead: see Workloads you already know are leaving above.
  • If every term for a family is withheld, no recommendation is shown for it at all, and any recommendation already open for that family is closed automatically on the next refresh.

Every commitment card carries a Covered this period figure: the dollars the latest closed bill charged to that benefit’s name. The month those dollars cover is printed right under the figure, and it is not the window the utilization percent beside it was measured over: your provider reports that one on its own trailing schedule, and we will not print one month’s label over another month’s number. Where the figure was modelled from your locked rate instead of read off a bill, that line says modelled in place of a month, and hovering it names the source.

Where no bill named the benefit and there was no locked rate to model from, the cell reads —, never $0. A commitment nobody could measure is not a commitment that covered nothing; a reservation bought this month is the ordinary case, since no closed month has billed it yet.

Covered dollars and period waste are separate observations on different bases, so the page never adds them together into a total.

Your bill and your commitment inventory come from two different Azure APIs. Cost data always shows that a reservation discount was applied; listing the reservation itself (its term, rate, and utilization) needs the optional Reservations Reader role at tenant scope (Savings plan Reader for savings plans), which lives outside subscription RBAC.

When we see commitment discounts on your bill that we could not read, the Commitments page says so directly, names the benefits and their monthly cost, and tells you the role to grant, per kind: Reservations Reader for reservations (or, on an Enterprise Agreement, the Enrollment Reader billing role), Savings plan Reader for savings plans. Without it your commitments are billed but invisible: no utilization, no expiry warnings, no under-use findings. Grant it (see Connect a cloud account) and they appear on the next refresh.

Azure quotes a reservation’s price on the purchase order, not on the reservation, and the same Reservations Reader role reads it. Where the order carries a payment schedule we read your locked rate straight from it, and the Commitments page shows the rate, the period waste, and a cost-weighted average utilization.

Where the order carries no schedule at all (Enterprise Agreement, CSP and partner-billed orders in particular), we price the reservation from your own bill: what it charged per hour it covered last closed month, times its quantity. That is a rate, so period waste and under-use findings work as they do for a quoted price. Azure converts that bill to US dollars for the month, so if your enrollment is billed in another currency the rate moves with the exchange rate. When the bill cannot give an hourly rate (a reservation that ran fully idle, for example), we show what the bill charged it instead, and leave period waste blank. An order quoted only in your local currency is converted at the exchange rate your own bill states. An order holding several reservations of the same size is split across them by the quantity Azure itself bills on. Each of those is a derivation, not a quote, so the Commitments page shows the rate with an estimate badge that names where the number came from. A rate Azure quoted directly carries no badge: the distinction is the point.

Some orders survive all of that: several reservations of different sizes on one order, a local-currency quote in a currency your bill has never priced, or no amount anywhere. Those rows show — for locked rate and period waste. That dash means “Azure did not tell us the price”, never “this purchase is free”: the row is still counted, still tracked for expiry, and still flagged if it runs below the utilization floor; it simply is not given a dollar figure we would have had to invent. Under-use findings need a price to size the recovery, so they are raised for those rows only when the reservation’s own bill gives an hourly rate (see above).

Azure’s own recommendations, beside ours

Section titled “Azure’s own recommendations, beside ours”

Azure publishes reservation recommendations of its own, per subscription and per SKU and region. We show them on the Commitments page, in their own panel below our queue, exactly as Azure published them: the SKU, the region, the term, the quantity, and Azure’s net saving over its own look-back window in your billing currency.

They are not a correction of our numbers and our numbers are not a correction of theirs. Our sizing works per service family, which is why it can commit one amount across a family; Azure’s works per SKU and region, which is more precise but only for the shapes it has seen. The two answer different questions, so their savings are never added together and neither panel carries a total of the other. Use Azure’s rows to decide which SKU and region to buy in, and ours to decide how much to commit.

Commitments are largely one-way (they are not freely cancellable) so the pre-check is “will this baseline hold for the full term?”, validated with finance. leancosts produces the purchase parameters and the audit trail; it never executes the purchase. Follow Act on a cost finding.