Issue #3
Azure

Seven Ways to Cut Costs in Fabric, in Order

How to stop paying for idle Microsoft Fabric capacity, a two-command audit to find it, and what the April 2027 Azure OpenAI retirement does to your token bill.

CloudHiro FinOps Team
CloudHiro FinOps Team
November 9, 2026•10 min read
Seven Ways to Cut Costs in Fabric, in Order

Issue #03 · FinOps Uncensored • Production Reality Briefing


In this issue:


Latest News from the world of FinOps

Azure OpenAI GPT-4o, GPT-4o-mini and GPT-4.1-mini retire on 14 April 2027

Azure

Microsoft has notified Azure OpenAI customers (Service Health tracking ID MR5M-CG0) that four model versions will be retired on 14 April 2027. After that date they will no longer be available or operable. Each one has a default replacement, and which replacement you get depends on how the deployment is set up.

What's retiring and what replaces it

ModelVersionGlobal & Data Zone replacementRegional replacement
GPT-4o2024-08-06gpt-6-luna (2026-09-22)gpt-5.1 (2025-11-13)
GPT-4o2024-11-20gpt-6-luna (2026-09-22)gpt-5.1 (2025-11-13)
GPT-4o-mini2024-07-18gpt-6-luna (2026-09-22)gpt-5-mini (2025-08-07)
GPT-4.1-mini2025-04-14gpt-6-luna (2026-09-22)gpt-5-mini (2025-08-07)

Note: These are the default replacements from the Service Health notice. Microsoft's public retirement schedule may lag behind it, so check the notice in your own tenant (Azure portal → Service Health) for the upgrade target of each deployment.

What happens to your deployments

  • Standard deployments set to auto-upgrade move to the default replacement automatically on the retirement date.
  • Provisioned (PTU) deployments are never upgraded for you. You have to migrate them yourself, to the model of your choice.
  • Deployments with auto-upgrade turned off stop working on 14 April 2027 (requests return 410 Gone) unless you redeploy them on a supported model.

What it does to your bill

For most Global and Data Zone workloads the change is good news: gpt-6-luna is priced well below every retiring model, up to 96% cheaper than GPT-4o. The risk sits on the Regional path. A Regional GPT-4o-mini deployment moves to gpt-5-mini, whose output price is 3.3 times higher. Because gpt-5-mini is a reasoning model, its "thinking" tokens are billed as output too, so the real cost per request rises by more than that. The full pricing breakdown below has the numbers for each model.

⚡ The Catch: Global moves get cheaper, up to −96% on GPT-4o. Regional GPT-4o-mini moves to gpt-5-mini at 3.3x the output price, before reasoning tokens are counted.

What to do before 14 April 2027

  1. 1List your deployments on the retiring versions and note each one's deployment type and upgrade setting.
  2. 2Test the replacement model on real prompts for quality, latency and cost, as Microsoft recommends.
  3. 3Move Regional GPT-4o-mini workloads to Global or Data Zone gpt-6-luna where your data-residency rules allow it.
  4. 4Plan and run the migration for every Provisioned (PTU) deployment early, while capacity is still available in your region.

🔗 Official Azure OpenAI retirement schedule →


Anthropic halves prompt-cache reads on Claude Sonnet 5.5 to $0.10/1M tokens

Anthropic

Since 7 October 2026, cached input on Claude Sonnet 5.5 costs $0.10 per 1M tokens instead of $0.20. That is 5% of the $2.00 base input price, down from 10%. Cache writes and all other Sonnet 5.5 prices are unchanged. Reused context such as long system prompts, documentation or codebases now costs 95% less than sending it fresh.

Claude Sonnet 5.5 (per 1M tokens)Price
Base input$2.00
Cache write, 5-minute cache (1.25x input)$2.50
Cache write, 1-hour cache (2x input)$4.00
Cache read, before 7 Oct 2026$0.20
Cache read, from 7 Oct 2026$0.10
Output$10.00

Who benefits

Any workload that sends the same large prefix again and again: agents with long system prompts and tool definitions, chat over the same documents, and coding assistants that resend a codebase. The cheaper the cache read, the bigger the gap between a well-cached workload and one that misses the cache.

⚡ The Catch: Writing to the cache costs more than a normal request (1.25x base input for 5 minutes, 2x for 1 hour), and changing one byte early in the prompt makes everything after it a fresh, full-price write again.

How to get the saving

  1. 1Put stable content first (system prompt, tool definitions, reference documents) and the changing content (the user's question, timestamps, request IDs) after it.
  2. 2Keep the prefix byte-for-byte identical between requests. A timestamp or a reordered tool list at the top breaks the cache for everything after it.
  3. 3Check cache_read_input_tokens in the API response. If it stays at zero on repeated requests, something in the prefix is changing.
  4. 4Use the 1-hour cache only when the same prefix is reused across more than a few minutes. Its write costs 2x input, so it needs more reads to pay off.

🔗 Anthropic release notes, 7 October 2026 →


How to cut your Microsoft Fabric capacity costs

Azure

With Microsoft Fabric you pay for the size of the capacity you run, every hour it runs, not for the compute you actually use. A capacity sized for one busy hour costs the same during the 23 quiet ones. Most savings come from closing that gap: matching the size to the real load, moving load out of the peaks, and stopping or committing where it makes sense.

First, understand how Fabric counts load

Every Fabric SKU gives you a fixed number of capacity units (CU): an F64 has 64, an F32 has 32. Three rules decide how far you can safely shrink:

  • Smoothing. Background work (refreshes, pipelines, notebooks) is spread over 24 hours. Interactive work (people using reports) is spread over just 5 to 64 minutes, so it causes the sharp peaks.
  • Throttling. Fabric lets you borrow ahead. Once more than 10 minutes of future capacity is used up, interactive requests are delayed. After 60 minutes they're rejected. When a full 24 hours is used up, background jobs are rejected too.
  • Halving the SKU doubles the CU %. The work stays the same but the capacity is half the size. A capacity at 30% on F64 runs at about 60% on F32.

The Capacity Metrics app shows these numbers for each capacity. Look at 30 days, not one day.

Seven ways to cut costs, in order

  1. 1Remove what nobody uses. Delete capacities with no workspaces or almost no load, or move their workspaces onto a shared capacity. These are the easiest savings.
  2. 2Migrate legacy P SKUs. Microsoft no longer sells P SKUs, and each one retires at the end of its agreement term. Migration isn't automatic: buy the F SKU (P1 maps to F64 by capacity units), move the workspaces, then cancel the P SKU. Use the move to right-size too. F SKUs can be paused, resized and reserved, and F64 is a safe landing point for a P1, not a required one.
  3. 3Right-size. A good rule of thumb: downsize when the average load would stay at or below about 60% on the smaller SKU and the busiest 24 hours at or below about 80%. If a smaller SKU would cause rejections, keep the current size and work on the peaks first.
  4. 4Move background jobs out of the peak hours. Find the busiest hours and reschedule refreshes, pipelines and notebooks to quiet ones, often early morning or the weekend. Don't start every job on the hour.
  5. 5Make the interactive load lighter. When the peaks come from report users, rescheduling won't help. Optimize the heaviest reports and semantic models: fewer visuals per page, simpler DAX, aggregations, import instead of DirectQuery where you can, and incremental refresh. Once the peaks are lower, try the smaller SKU again.
  6. 6Pause what doesn't need to run 24/7. Pay-as-you-go capacities can be paused. Dev, test and business-hours-only capacities can be paused overnight and at weekends, either on a schedule or with a script. Don't pause an F64 that free viewers rely on: they can't open reports while it's paused.
  7. 7Reserve what does run 24/7. For capacities that run all the time at a stable size, a 1-year reservation costs roughly 41% less than pay-as-you-go (an F64 in East US is about $5,003 a month reserved vs $8,410). Buy it last, only once the size is final.

Mistakes to avoid

  • Reserving before you resize. A reservation locks in a size. Shrink first, then reserve.
  • Sizing for the peak. One busy hour shouldn't decide the bill for the whole month. Fix the peak, then size for the normal load.
  • Dropping below F64 without checking licences. Below F64, every report viewer needs a Power BI Pro or PPU licence (Pro is about $14 per user per month, and it's included in Microsoft 365 E5). Against a reserved F64, a reserved F32 saves money only if fewer than about 180 viewers would need a new licence.
  • Pausing an overloaded capacity. Pausing settles any borrowed capacity straight away, and it shows up on the bill. Pause when the load is quiet.
  • Forgetting storage. OneLake storage is billed separately and keeps growing. Clean up unused lakehouses, old tables and test copies.
  • Leaning on overage. Compute above your capacity can be billed as overage at three times the pay-as-you-go rate, with no reservation discount, and overage is switched on by default for new capacities. Treat it as a safety net with a limit you set, not a way to run a smaller SKU.

Where to start

Pick your most expensive capacity and look at its last 30 days. If the average is below about 30%, there's almost certainly a smaller size that fits. Then work down the list: remove, resize, smooth the peaks, pause, and reserve last. After each change, watch throttling for a week before you take the next step.


Actionable Playbook · Discovery Script

Audit every Fabric capacity you pay for, then pause the ones that sleep

Steps 1, 6 and 7 above all start with the same question: which F SKU capacities exist, how big are they, and are they running right now? Fabric capacities are ordinary Azure resources, so one Azure Resource Graph query answers it across every subscription you can read, with a list-price estimate of what each one costs on pay-as-you-go.

Step 1: List every Fabric capacity and its PAYG cost

Run this in Azure Cloud Shell (Bash) or any terminal with the Azure CLI signed in. The first run may ask to install the resource-graph CLI extension.

list_fabric_capacities.sh
1# 0.18 = East US PAYG price per CU-hour. Replace it with your region's rate.
2az graph query --first 1000 -o table -q "
3resources
4| where type =~ 'microsoft.fabric/capacities'
5| extend Sku = tostring(sku.name), State = tostring(properties.state)
6| extend CUs = toint(substring(Sku, 1))
7| extend EstPAYGMonthlyUSD = round(CUs * 0.18 * 730, 0)
8| project name, resourceGroup, location, Sku, CUs, State, EstPAYGMonthlyUSD, subscriptionId
9| order by CUs desc"
Read-Only ARM Query•Zero infrastructure modification
Requires: az CLI

How to read the result:

  • Sku and CUs: the number after the F is the capacity's CU count (F64 = 64 CUs).
  • State: Active capacities are billing every hour; paused ones (shown as Paused or Suspended) are not billing for compute.
  • EstPAYGMonthlyUSD: CUs × $0.18 × 730 hours, the list price if the capacity runs all month. An F64 comes to about $8,410. Capacities covered by a reservation cost less than this.

Legacy P SKUs are bought through Microsoft 365, not Azure, so they won't appear in this query. Find them in the Fabric admin portal under Capacity settings.

Step 2: Pause a dev, test or business-hours capacity (and resume it)

pause_resume_fabric_capacity.sh
1# Fill in the values from Step 1
2SUB=<subscription-id>; RG=<resource-group>; CAP=<capacity-name>
3URL="https://management.azure.com/subscriptions/$SUB/resourceGroups/$RG/providers/Microsoft.Fabric/capacities/$CAP"
4az rest --method post --url "$URL/suspend?api-version=2023-11-01" # pause
5az rest --method post --url "$URL/resume?api-version=2023-11-01" # resume
Modifies Resources•Review the checklist before running
Requires: az CLI

What it saves: an F8 dev capacity costs about $1,051 a month running 24/7 (8 × $0.18 × 730 hours). Running it only 10 hours a day on 22 working days (220 hours) brings it to about $317, saving roughly $734 a month, or 70%.

Run it on a schedule: put the two commands in an Azure Automation runbook or a Logic App, with a managed identity that has Contributor rights on the capacity. Resume it before the working day starts and pause it after the last scheduled job finishes.

Safety checklist before you pause

  • Don't pause an F64 or larger that free users rely on. They can't open reports while it's paused.
  • Pausing a reserved capacity saves nothing, because the reservation keeps billing.
  • Any smoothed usage still waiting to be burned down is billed the moment you pause, so pause after the day's heavy jobs, not in the middle of them.
  • Refreshes, pipelines and notebooks scheduled during the pause will fail. Move them or resume first.

🔗 Microsoft guide: pause and resume a Fabric capacity →


Cost Comparisons · Azure OpenAI Retirement (14 April 2027)

Retiring models vs. default replacement pricing (per 1M tokens)

Before letting Azure auto-upgrade your deployments on 14 April 2027, compare the pay-as-you-go token rates on each replacement path. All prices are Global Standard list prices in US dollars per 1 million tokens, shown as Input / Cached input / Output. Data Zone and Regional deployments cost roughly 10% more, but because that premium applies to both the retiring and the replacement model, the percentage changes stay the same. Check the Azure OpenAI pricing page for your exact region and deployment type.

Retiring modelCurrent priceGlobal / Data Zone: gpt-6-lunaRegional: gpt-5.1 / gpt-5-miniNet cost impact
GPT-4o (2024-08-06 & 2024-11-20)$2.50 / $1.25 / $10.00$0.10 / $0.01 / $0.50gpt-5.1: $1.25 / $0.125 / $10.00Global: −96% input, −99% cached, −95% output. Regional: −50% input, −90% cached, flat output.
GPT-4o-mini (2024-07-18)$0.15 / $0.075 / $0.60$0.10 / $0.01 / $0.50gpt-5-mini: $0.25 / $0.025 / $2.00Global: −33% input, −87% cached, −17% output. Regional TRAP: +67% input, −67% cached, +233% output (3.3x).
GPT-4.1-mini (2025-04-14)$0.40 / $0.10 / $1.60$0.10 / $0.01 / $0.50gpt-5-mini: $0.25 / $0.025 / $2.00Global: −75% input, −90% cached, −69% output. Regional: −37.5% input, −75% cached, +25% output.

gpt-6-luna prices are for standard-length prompts. Long-context requests on gpt-6-luna are billed at a higher rate, so check the long-context price if your prompts are very large.

Three things the price table doesn't show

  1. 1Reasoning tokens are billed as output. gpt-5-mini is a reasoning model and always thinks: the tokens it spends "thinking" are charged at the output rate, so its 3.3x higher output price turns into an even bigger bill per request. It doesn't accept none, so set reasoning_effort to minimal for simple, non-reasoning tasks. gpt-5.1 defaults to none, so it only spends reasoning tokens if your code raises the effort. Check that migrated calls don't.
  2. 2Cheaper usually means smaller. A model priced 96% below GPT-4o is unlikely to behave exactly like it. Test output quality on your own prompts before you switch production traffic, as Microsoft itself recommends.
  3. 3Moving to Global changes where data is processed. The cheapest path for Regional workloads is Global or Data Zone gpt-6-luna, but only where your data-residency rules allow it.

⚡ Cost Verdict: Migrating Global or Data Zone workloads to gpt-6-luna ($0.10/1M input, $0.01/1M cached, $0.50/1M output) cuts token prices on every retiring model, by 17% to 96% depending on the model: GPT-4o-mini sees the smallest drop and GPT-4o the largest. Test quality first. Do not let Regional GPT-4o-mini deployments blindly auto-upgrade to gpt-5-mini ($2.00/1M output vs $0.60/1M). Move eligible workloads to Global or Data Zone gpt-6-luna instead, keep reasoning effort low for non-reasoning tasks, and schedule manual migrations for all Provisioned (PTU) deployments before 14 April 2027.


Are you coming to Microsoft Ignite?

Meet the CloudHiro team in San Francisco

17–20 November 2026 · Moscone Center, San Francisco. Meet the CloudHiro team and discover how we bring Azure-native FinOps intelligence and cloud cost optimization to enterprise environments.

👉 Schedule a meeting →

To cleaner architectures and lower cloud bills,
The CloudHiro Team

Share this issue: