You have built the lakehouses, warehouses, notebooks, and pipelines. Everything works in development. Then the bill arrives: “Fabric capacity usage: 85% consumed. Throttling applied. Pipeline runs delayed by 30 minutes.”
Understanding HOW Fabric charges, WHAT consumes capacity, and HOW to optimize cost is the difference between a well-managed platform and an unexpected budget overrun. This post covers everything a data engineer and admin needs to know about Fabric capacity, cost, and optimization.
Think of Fabric capacity like a hotel with a fixed number of rooms (CUs). Guests (workloads) check in and use rooms. If all rooms are full (capacity exhausted), new guests wait in the lobby (throttling). The hotel manager (admin) must balance occupancy — too few guests wastes money, too many creates delays. This post teaches you to be an effective hotel manager.
Table of Contents
- What Are Capacity Units (CUs)?
- F-SKUs vs P-SKUs
- How Workloads Consume CUs
- CU Consumption by Workload Type
- Throttling: What Happens When Capacity Is Exceeded
- Smoothing: How Fabric Spreads the Load
- The Burst and Smoothing Model Explained
- Monitoring Capacity Usage
- Microsoft Fabric Capacity Metrics App
- Admin Portal Monitoring
- Pause and Resume Capacity
- When to Pause
- Autoscale
- Cost Optimization Strategies
- Right-Size Your Capacity
- Optimize Notebook and Spark Usage
- Optimize Pipeline Scheduling
- Use Starter Pools
- Optimize Delta Tables (OPTIMIZE, V-Order)
- Avoid Unnecessary Refreshes
- F-SKU Sizing Guide
- Real-World Cost Scenarios
- Scenario 1: Small Team (5 engineers, 10 analysts)
- Scenario 2: Medium Enterprise (20 engineers, 50 analysts)
- Trial and Pay-As-You-Go Options
- Common Mistakes
- Interview Questions
- Wrapping Up
What Are Capacity Units (CUs)?
A Capacity Unit (CU) is Fabric’s universal compute currency. Every operation — notebook run, pipeline execution, SQL query, Power BI refresh, Dataflow Gen2 run — consumes CUs. Your Fabric capacity has a fixed number of CUs per second.
Capacity: F64 (64 CU seconds per second)
→ Can process 64 CU-seconds of work every second
→ If a notebook needs 32 CUs for 10 seconds = 320 CU-seconds
→ The F64 can run this notebook while still having 32 CUs for other work
F-SKUs vs P-SKUs
| SKU | CUs | Price (approx/month) | Includes Power BI? | Best For |
|---|---|---|---|---|
| F2 | 2 | ~$262 | No | Dev/test, learning |
| F4 | 4 | ~$524 | No | Small team dev |
| F8 | 8 | ~$1,048 | No | Small production |
| F16 | 16 | ~$2,096 | No | Medium workloads |
| F32 | 32 | ~$4,192 | No | Medium-large |
| F64 | 64 | ~$8,384 | Yes (P1 equivalent) | Enterprise |
| F128 | 128 | ~$16,768 | Yes (P2 equivalent) | Large enterprise |
| F256 | 256 | ~$33,536 | Yes (P3 equivalent) | Very large |
| F512 | 512 | ~$67,072 | Yes (P4 equivalent) | Maximum |
F64 and above include Power BI Premium per-capacity features. Below F64, you need separate Power BI Pro licenses.
How Workloads Consume CUs
CU Consumption by Workload Type
| Workload | CU Consumption | Notes |
|---|---|---|
| Spark (notebooks) | High | Depends on cluster size, duration |
| Pipeline runs | Low-Medium | CUs for orchestration + activities |
| Copy Activity | Medium | Depends on data volume |
| Dataflow Gen2 | Medium | Power Query processing |
| SQL Warehouse queries | Medium | Depends on query complexity |
| SQL Lakehouse endpoint | Low-Medium | Read-only queries |
| Power BI Direct Lake | Low | Reads Delta files (very efficient) |
| Power BI Import refresh | Medium | Data load into VertiPaq |
| KQL queries | Low-Medium | Depends on data volume scanned |
| Mirroring | Free compute | Only storage costs |
| OneLake storage | Per GB/month | ~$0.023/GB/month |
Throttling: What Happens When Capacity Is Exceeded
Scenario: F16 capacity (16 CUs/second)
8:00 AM: Notebook uses 10 CUs → 6 CUs remaining → OK ✅
8:01 AM: Pipeline uses 8 CUs → total 18 CUs → EXCEEDS 16 CU limit
What happens:
Interactive jobs (SQL queries, report views): throttled first (slower)
Background jobs (pipelines, refreshes): delayed or queued
Throttling levels:
10-minute window exceeded → interactive throttling (queries slow down)
60-minute window exceeded → background throttling (pipelines delayed)
24-hour window exceeded → severe throttling (rejections possible)
Smoothing: How Fabric Spreads the Load
Fabric does NOT bill per-second peak usage. It uses smoothing — averaging consumption over time windows:
The Burst and Smoothing Model Explained
Without smoothing:
8:00 AM: 100 CUs consumed (spike!) → immediate throttling on F64
With smoothing:
Fabric averages over 5-minute windows:
8:00-8:05 AM: Peak was 100 CUs, but average is 40 CUs → within F64 limit → no throttling
Allows short BURSTS above capacity without penalty.
Only sustained over-usage triggers throttling.
How it works in practice:
Your F64 capacity = 64 CUs/second
Smoothing window: Fabric evaluates over rolling time periods
BURST ALLOWED:
A notebook spikes to 200 CUs for 30 seconds
→ Smoothed over the 5-minute window: 200*30 / 300 = 20 CU average → OK ✅
THROTTLING TRIGGERED:
5 notebooks each using 50 CUs running for 10 minutes straight
→ Sustained 250 CUs vs 64 capacity → throttling kicks in after ~10 minutes
The rule: Short spikes (a heavy notebook for 2 minutes) are absorbed. Sustained overload (5+ pipelines running for 30 minutes) triggers throttling. Design your workloads to have sharp peaks (finish quickly) rather than sustained plateaus (run slowly for a long time).
Monitoring Capacity Usage
Microsoft Fabric Capacity Metrics App
- Open the Fabric Admin Portal
- Install the Microsoft Fabric Capacity Metrics app from AppSource
- Connect to your capacity
- Dashboard shows:
- CU utilization over time (line chart)
- Throttling events (when and how severe)
- Top consumers (which workloads use the most CUs)
- Overages by workspace and item
Admin Portal Monitoring
The Fabric Admin Portal provides built-in monitoring without installing additional apps:
Access: Fabric portal → Settings (gear icon) → Admin portal
Key sections:
Capacity settings → Select your capacity → see:
- Current utilization percentage
- Throttling status (green/yellow/red)
- Workspaces assigned to this capacity
Usage metrics → See per-workspace breakdown:
- Which workspace consumes the most CUs
- Peak hours of consumption
- Background vs interactive split
Tenant settings → Control what users can do:
- Who can create workspaces
- Who can use specific workloads (Spark, Dataflows)
- Export and sharing controls
- Git integration settings
Tip: For detailed per-item CU breakdown (which specific notebook or pipeline consumed the most), use the Capacity Metrics App. The Admin Portal gives workspace-level overview; the Metrics App gives item-level detail.
Key Metrics to Watch
| Metric | Healthy | Warning | Critical |
|---|---|---|---|
| CU utilization (avg) | < 60% | 60-80% | > 80% |
| Throttling events/day | 0 | 1-5 | > 5 |
| Background job delays | 0 min | < 15 min | > 30 min |
Pause and Resume Capacity
When to Pause
You can pause your capacity to stop ALL billing (except OneLake storage):
Pause:
→ All compute stops (no notebooks, pipelines, queries)
→ Data in OneLake persists (storage still billed)
→ Scheduled pipelines will NOT run while paused
→ Users cannot query SQL endpoints or open reports
Resume:
→ Capacity starts within 1-2 minutes
→ All items available again
→ Missed pipeline schedules do NOT auto-catch-up
When to pause:
✅ Dev/test environments during nights and weekends
✅ Training/demo capacities after workshops
✅ Seasonal workloads (pause during off-season)
❌ NEVER pause production if pipelines run overnight
❌ NEVER pause if Power BI reports need 24/7 access
Automate with Azure: Use Azure Automation or Logic Apps to pause at 8 PM and resume at 7 AM on weekdays — save ~50% on dev capacity.
Autoscale
Autoscale automatically adds CUs when demand exceeds your base capacity, preventing throttling during peak hours:
Setup: Azure portal → Fabric capacity → Scale → Enable Autoscale
Base capacity: F32 (32 CUs)
Autoscale max: +32 CUs (total 64 CUs during peaks)
How it works:
Normal hours: uses base 32 CUs → standard billing
8:00 AM ETL spike: demand hits 50 CUs → autoscale adds 18 CUs → no throttling
8:30 AM spike ends: autoscale releases extra CUs → back to base billing
Billing:
Autoscale CUs are billed per-second at pay-as-you-go rates
You only pay for extra CUs when they are actually used
Set a max CU limit to prevent runaway costs
Best practice: Use autoscale as a safety net — not a primary strategy. If you autoscale regularly, it is cheaper to upgrade to the next SKU. Autoscale is for unexpected spikes, not predictable daily peaks.
Cost Optimization Strategies
Right-Size Your Capacity
Observation: Average CU usage is 15% on F64
→ Downgrade to F16 (saves ~$6,000/month)
Observation: Frequent throttling on F16
→ Upgrade to F32 or optimize workloads first
Optimize Notebook and Spark Usage
# ❌ WASTEFUL: Large cluster for small data
# Session with 8 executors processing 10,000 rows
# ✅ OPTIMIZED: Match cluster to data size
spark.conf.set("spark.sql.shuffle.partitions", "10") # Not 200 for small data
# Use starter pools for quick ad-hoc queries (lower CU footprint)
Optimize Pipeline Scheduling
❌ WASTEFUL: 10 pipelines all scheduled at 6:00 AM (massive CU spike)
✅ OPTIMIZED: Stagger pipelines:
6:00 AM: Pipeline 1 + 2
6:15 AM: Pipeline 3 + 4
6:30 AM: Pipeline 5 + 6
Spreads the load, avoids throttling
Use Starter Pools
Starter pools are pre-warmed Spark clusters maintained by Fabric — they start in ~10 seconds and use fewer CUs than custom environments:
Custom Spark Environment:
Startup: 1-3 minutes (CUs consumed during startup)
Configuration: your custom libraries, settings
Best for: production notebooks with specific library requirements
Starter Pool:
Startup: ~10 seconds (minimal CU overhead)
Configuration: Fabric defaults only
Best for: ad-hoc queries, data exploration, quick validations
CU savings: Starter pools avoid the 1-3 minute cluster provisioning overhead
10 engineers each running 5 ad-hoc queries/day with custom environments:
50 sessions × 2 min startup × CU cost = significant waste
Same with starter pools:
50 sessions × 10 sec startup = ~90% less startup CU consumption
Optimize Delta Tables (OPTIMIZE, V-Order)
-- Run OPTIMIZE weekly (fewer files = faster reads = less CU)
OPTIMIZE gold.fact_sales;
-- V-Order (automatically applied in Fabric, ensures optimal read pattern)
-- Result: Direct Lake and SQL queries use significantly less CU
-- The impact is real:
-- Unoptimized table (10,000 small files): SQL query scans all files → 50 CU-seconds
-- Optimized table (100 large files): SQL query scans less → 5 CU-seconds
-- 10x CU savings per query × hundreds of queries/day = massive savings
Avoid Unnecessary Refreshes
❌ WASTEFUL:
Power BI Import dataset refreshing every 30 minutes
when source data only updates once daily at 6 AM
→ 47 unnecessary refreshes/day × CU cost = wasted compute
✅ OPTIMIZED:
Switch to Direct Lake mode (no refresh needed — reads Delta files directly)
OR set Import refresh to once daily at 7 AM (after pipeline completes)
❌ WASTEFUL:
Pipeline runs every 15 minutes but source only has new data hourly
→ 3 out of 4 runs do nothing but still consume CUs for orchestration
✅ OPTIMIZED:
Use event-based triggers (run only when new files land)
OR run hourly instead of every 15 minutes
OR add a check: IF no new files → skip (Web activity + If Condition)
Pause Dev/Test Capacities
Production capacity: F32, always on
Dev capacity: F4, paused nights and weekends
→ Saves ~65% on dev capacity (~$340/month saved)
F-SKU Sizing Guide
| Team Size | Workload | Recommended SKU | Monthly Cost |
|---|---|---|---|
| 1-3 engineers, learning | Light dev/test | F2 | ~$262 |
| 3-5 engineers, dev | Medium development | F4 | ~$524 |
| 5-10 engineers, small prod | Production workloads | F8-F16 | ~$1,048-$2,096 |
| 10-20 engineers, enterprise | Heavy production + Power BI | F32-F64 | ~$4,192-$8,384 |
| 20+ engineers, large enterprise | Multi-team, heavy analytics | F128+ | ~$16,768+ |
Real-World Cost Scenarios
Scenario 1: Small Team (5 engineers, 10 analysts)
Company: Mid-size retailer, first Fabric deployment
Capacity: F8 ($1,048/month)
Dev workspace: 3 lakehouses, 5 notebooks, 2 pipelines
Prod workspace: 1 lakehouse, 1 warehouse, 3 pipelines, 5 Power BI reports
Daily workload:
6:00 AM: 3 pipelines (Copy + Notebook) → ~45 min total → moderate CU
Throughout day: 10 analysts querying SQL endpoint → low CU (read-only)
Power BI Direct Lake: auto-serves reports → very low CU per query
Monthly cost breakdown:
F8 capacity: $1,048
OneLake storage: ~$15 (650 GB × $0.023)
Total: ~$1,063/month
Optimization:
Pause dev workspace capacity on weekends → save ~$150/month
Use starter pools for ad-hoc exploration → avoid custom Spark overhead
Scenario 2: Medium Enterprise (20 engineers, 50 analysts)
Company: Financial services, multiple departments
Capacities:
Production: F64 ($8,384/month) — always on
Dev/Test: F8 ($1,048/month) — paused nights/weekends
Daily workload:
6:00-7:00 AM: 15 pipelines (staggered every 5 min) → high CU for 1 hour
7:00-8:00 AM: 10 Spark notebooks (Silver → Gold transforms) → high CU
8:00 AM-6:00 PM: 50 analysts querying + Power BI reports → steady medium CU
Real-time: 1 Eventstream → Eventhouse (IoT monitoring) → low sustained CU
Monthly cost breakdown:
F64 production: $8,384
F8 dev (paused): $524 (50% savings from pausing)
OneLake storage: ~$115 (5 TB × $0.023)
Total: ~$9,023/month
Optimization applied:
Staggered pipelines → eliminated throttling (was causing 30-min delays)
OPTIMIZE on Gold tables → 40% reduction in SQL query CU
Direct Lake → eliminated 8 scheduled Import refreshes/day
Autoscale +16 CUs on F64 → handles quarterly reporting spikes
Trial and Pay-As-You-Go Options
| Option | What You Get | Duration | Best For |
|---|---|---|---|
| Free trial | F64 equivalent capacity | 60 days | Evaluating Fabric, building POCs, learning |
| Pay-as-you-go (PAYG) | Per-second billing, any F-SKU | No commitment | Unpredictable workloads, testing before committing |
| Reserved capacity | 1-year or 3-year commitment | 1 or 3 years | Predictable workloads, 40-65% savings vs PAYG |
Free trial:
Sign up at app.fabric.microsoft.com → Start trial
60 days of F64-equivalent capacity
After trial: data persists in OneLake but compute stops (cannot run queries/pipelines)
Convert to paid capacity to resume
Pay-as-you-go:
Azure portal → Create resource → Microsoft Fabric Capacity
Billed per-second — only pay while capacity is running
Pause/resume anytime
No commitment — ideal for seasonal or experimental workloads
Reserved capacity:
1-year reservation: ~40% savings vs PAYG
3-year reservation: ~65% savings vs PAYG
Best for production workloads with predictable, steady usage
Cannot be paused (you pay regardless of usage)
Common Mistakes
-
Over-provisioning capacity — running F64 when F16 is sufficient wastes $6,000/month. Monitor actual usage first, then right-size.
-
Not monitoring throttling — throttling silently delays pipelines. If your 6 AM ETL is supposed to finish by 7 AM but throttling pushes it to 8 AM, dashboards show stale data. Monitor proactively.
-
Scheduling all pipelines at the same time — creates massive CU spikes. Stagger by 10-15 minutes.
-
Not pausing dev/test capacities — paying for 24/7 capacity that is used 8 hours/day wastes 67% of the cost.
-
Ignoring Spark session cleanup — orphaned Spark sessions consume CUs. Set idle timeouts and close sessions after notebooks complete.
Interview Questions
Q: How does billing work in Microsoft Fabric? A: Fabric uses Capacity Units (CUs) as a universal compute currency. You purchase a capacity (F2 to F512) with a fixed number of CUs per second. All workloads (notebooks, pipelines, queries, Power BI) consume CUs from this shared pool. Smoothing averages consumption over time windows, allowing short bursts. Sustained overuse triggers throttling. Storage (OneLake) is billed separately per GB/month.
Q: What is throttling and how do you prevent it? A: Throttling occurs when CU consumption exceeds capacity. Interactive queries slow down first, then background jobs are delayed. Prevention: right-size capacity based on actual usage, stagger pipeline schedules, optimize Spark configurations, run OPTIMIZE on Delta tables, and pause unused dev/test capacities.
Wrapping Up
Fabric capacity management is about balance — enough CUs for your workloads without overspending. Monitor usage with the Capacity Metrics app, right-size your SKU, stagger heavy workloads, pause dev environments, and optimize Spark and Delta tables. The goal is consistent CU utilization around 50-70% — enough headroom for spikes without wasting money.
Related posts: – Fabric Foundations – Security & Governance – Fabric Notebooks – Delta Lake Optimization
Naveen Vuppula is a Senior Data Engineering Consultant and app developer based in Ontario, Canada. He writes about Python, SQL, AWS, Azure, and everything data engineering at DriveDataScience.com.