Microsoft Fabric Capacity Governance: concurrency, smoothing en bescherming van kritieke workloads
Gemiddelde benutting vertelt je niet waarom Fabric traag aanvoelt. Smoothing, carryforward en slechte plaatsing van workloads wel. Zo stuur je je capacity voordat achtergrondjobs je interactieve gebruikers raken.
fabric · capacity-planning · governance · performance · monitoring
Fabric-capacityproblemen beginnen zelden met een grote storing. Meestal begint het met iemand die zegt: "Dit rapport voelt de laatste tijd nogal willekeurig."
Om 9:15 is het semantic model traag. Om 9:20 niet meer. Je dagelijkse utilization lijkt 45%, dus iedereen neemt aan dat de SKU groot genoeg is. Daarna vallen een refresh-keten, een paar notebooks en een warehouse-ingestievenster samen, en krijgen gebruikers vertraging of zelfs afwijzingen.
Dat is precies de valkuil. In Fabric is gemiddelde benutting een geruststellende grafiek. Het is geen operationeel model.
Herzien april 2026
Deze post is gebaseerd op het huidige gedrag van Fabric rond throttling, surge protection en workload management voor warehouses. Microsoft verandert dit soort details regelmatig, dus controleer drempelwaarden en platformgedrag altijd eerst in je eigen tenant voordat je regels in productie aanscherpt.
Waarom gemiddelde benutting misleidt
Fabric rekent capaciteitsdruk niet alleen af op het moment dat een job draait. Het platform gebruikt bursting en smoothing.
- Interactieve operaties worden gladgestreken over minimaal 5 minuten en maximaal 64 minuten.
- Achtergrondoperaties worden over 24 uur uitgesmeerd.
- Evaluatie gebeurt in tijdvakken van 30 seconden.
Daardoor kan een zware achtergrondjob snel klaar zijn, succesvol lijken, en toch een lange staart aan reeds geclaimde toekomstige capacity achterlaten. In Fabric-termen is dat carryforward. De rustige periodes daarna zijn in feite bezig met het terugbetalen van compute die je al hebt verbruikt.
Dat is de reden dat een capacity in de ochtend traag kan aanvoelen terwijl de nachtelijke load al klaar is. De compute is gisteren al opgebruikt. De rekening komt nu pas binnen.
Warehouse maakt dit nog verwarrender. De meeste Warehouse- en SQL analytics endpoint-operaties worden als background geclassificeerd zodat ze profiteren van 24-uurs smoothing. Dat is prettig voor throughput, maar het betekent ook dat zware warehouse-activiteit ongemerkt de headroom van morgen kan opeten als je naar de verkeerde grafieken kijkt.
Vraag dus niet alleen: "Wat was gisteren mijn gemiddelde utilization?" Stel liever deze vragen:
- Hoeveel 10-minuten headroom had ik tijdens kantooruren?
- Hoeveel 24-uurs background-budget was al opgebruikt voordat gebruikers inlogden?
- Welke workspaces veroorzaakten de carryforward?
Als je al platformdata verzamelt, leg discovery-data en runtime-druk dan niet op één hoop. Het zijn twee verschillende problemen. Wie die door elkaar haalt, stuurt op het verkeerde niveau.
De drie throttling-fases die echt tellen
Fabric gaat niet in één klap van gezond naar onbruikbaar. Het platform zakt weg in fases.
1. Interactive delay
Zodra de volgende 10 minuten aan toekomstige capacity in feite vol zitten, krijgen nieuwe interactieve operaties 20 seconden vertraging. Gebruikers ervaren dit als "Fabric voelt ineens stroperig."
2. Interactive rejection
Als het volgende uur vol zit, worden nieuwe interactieve operaties afgewezen. Op dit punt zien rapportgebruikers en analisten niet alleen traagheid, maar ook fouten.
3. Background rejection
Als de volgende 24 uur vol zitten, weigert Fabric ook nieuwe achtergrondjobs. Dan ben je niet meer aan het load managen. Dan ben je aan het herstellen.
Twee praktische punten zijn hier belangrijk:
- Werk dat al gestart is, wordt niet halverwege afgeknepen. De volgende requests krijgen de klap.
- Een utilization-piek boven 100% betekent niet automatisch dat je throttling hebt. Je moet naar throttling en burndown kijken, niet alleen naar ruwe utilization.
Dat verschil is belangrijk omdat teams vaak te heftig reageren op één piek en te laat reageren op trage burndown. Het gevaarlijke scenario is niet "we hebben gepiekt." Het gevaarlijke scenario is "we betalen die piek nog steeds af wanneer de volgende werkdag begint."
Begin met blast radius, niet met afdelingsnamen
Veel Fabric-omgevingen zijn ingericht volgens het organogram. Finance krijgt een workspace. Sales krijgt een workspace. Data engineering krijgt een workspace. Daarna belandt alles op één gedeelde F64 omdat dat makkelijk is.
Makkelijk is niet hetzelfde als beheersbaar.
Een betere aanpak is om workloads te scheiden op basis van faalgedrag:
- Capacity A: mission-critical semantic models en executive reporting
- Capacity B: gedeelde engineeringworkloads zoals notebooks, Dataflows Gen2, pipelines en zware warehouse-ingestie
- Capacity C: dev, test, ad-hoc analyse en experimentele workloads
Als je kritieke BI en zware engineering op dezelfde capacity zet, maak je bewust de keuze dat background-werk je interactieve gebruikers mag beschadigen. Voor een klein team kan dat soms prima zijn. In productie meestal niet.
Dat betekent niet dat je al je data moet kopiëren. Gebruik OneLake shortcuts en gedeelde curated zones waar dat logisch is. Het doel is compute-isolatie, niet opslagchaos.
Twijfel je nog of een workload in een lakehouse of warehouse hoort, lees dan eerst lakehouse vs. warehouse in Fabric. Slechte capacity-governance begint vaak met de juiste engine voor het verkeerde gebruikspatroon.
Gebruik surge protection, maar doe niet alsof het architectuur is
Fabric surge protection is nuttig omdat je background-werk eerder kunt laten afwijzen dan met de standaardlimieten van het platform. Daarmee krijg je een kans om interactieve gebruikers te beschermen voordat de capacity in een diepe 24-uurs overload terechtkomt.
Een bruikbare startaanpak voor gedeelde capacities is:
- zet een background rejection threshold onder het punt waar het in jouw praktijk misgaat
- zet een recovery threshold onder je normale background-belasting
- bepaal beide op basis van de Compute-pagina in de Capacity Metrics-app, niet op gevoel
Als je background rejection normaal rond 35% ligt en op slechte dagen piekt naar 70%, dan is een drempel ergens tussen die twee waarden een logisch begin. Zet je hem op 95%, dan heb je feitelijk niets ingesteld. Zet je hem op 20%, dan wijs je de hele dag jobs af en geef je ten onrechte het platform de schuld.
Workspace-level surge protection is nog interessanter. Je kunt workspaces behandelen als:
- Available: normaal gedeeld gedrag
- Mission Critical: vrijgesteld van workspace-level blokkering
- Blocked: handmatig of automatisch geweigerd
Dit is een van de weinige echte governance-hefbomen die Fabric je geeft tegen noisy neighbors. Gebruik hem. Eén ontspoorde workspace mag niet een complete gedeelde capacity leegtrekken voor iedereen else.
Maar wees eerlijk over de beperking: mission-critical status heft algemene capacity-throttling niet op. Als de hele SKU vastloopt, heeft alsnog iedereen last. Surge protection is een vangrail. Geen vervanging voor isolatie van blast radius.
De workspace is je SQL-isolatiegrens
Warehouse-teams denken vaak alleen in tabellen en queries. In Fabric is de workspace-grens minstens zo belangrijk.
Voor Warehouse en SQL analytics endpoint heeft iedere workspace zijn eigen SQL-computegrens. Standaard splitst Fabric de beschikbare compute in gescheiden SELECT- en non-SELECT-pools. Die 50/50-verdeling bestaat niet voor niets: leesdruk en ingestiedruk horen elkaar niet te slopen.
Als één workspace tegelijk dashboardverkeer bedient en ETL-zware writes uitvoert, onderzoek dan eerst het workloadpatroon voordat je simpelweg een grotere SKU koopt.
Begin met de DMVs:
SELECT TOP 20
session_id,
status,
command,
total_elapsed_time_ms / 1000.0 AS elapsed_seconds,
submit_time
FROM sys.dm_exec_requests
ORDER BY total_elapsed_time_ms DESC;
Stel daarna een moeilijkere vraag: horen deze lezers en schrijvers eigenlijk wel op dezelfde workspace-engine thuis?
Voor leesintensieve patronen kun je curated tabellen via OneLake shortcuts in een tweede workspace aanbieden. Daarmee krijg je nog een SQL-isolatiegrens zonder een tweede kopie van de data te maken. Dat is vaak een schonere oplossing dan eindeloos sleutelen aan query time-outs in de hoop dat concurrency vanzelf beter wordt.
Verlaag background-verbruik voordat je opschaalt
Veel capacityproblemen zijn in werkelijkheid geen capacityproblemen. Het zijn verspillingproblemen.
Typische voorbeelden:
- Spark-jobs die veel meer data shufflen dan nodig is
- Delta tables met duizenden kleine bestanden
- refreshvensters die zonder zakelijke reden boven op elkaar gepland zijn
- notebooks voor workloads die prima in pandas of SQL passen
Los de duidelijke verspilling eerst op voordat je een capacity vergroot. Mijn gids voor Spark-optimalisatie in Fabric notebooks en gids voor Delta Lake-onderhoud gaan dieper in op de techniek. Op governance-niveau is de boodschap simpel: slechte fysica in één workload wordt gedeelde pijn voor alles wat op die capacity draait.
Hier is een klein voorbeeld van hoe je background-druk in een notebook verlaagt voordat die ooit op je capacity-budget drukt:
from pyspark.sql.functions import broadcast, col, current_date, date_sub, sum
spark.conf.set("spark.sql.adaptive.enabled", "true")
spark.conf.set("spark.sql.shuffle.partitions", "400")
sales = (
spark.table("sales")
.filter(col("date") >= date_sub(current_date(), 7))
.select("customer_id", "product_id", "amount", "date")
)
products = spark.table("dim_product").select("product_id", "category")
result = (
sales.join(broadcast(products), "product_id")
.groupBy("category")
.agg(sum("amount").alias("amount"))
)
result.write.mode("overwrite").saveAsTable("category_sales_last_7_days")
De code zelf is niet het belangrijkste punt. Het gaat erom dat minder shuffle, betere joins en minder verspilling bij writes ook minder 24-uurs last betekenen die je volledige capacity moet dragen.
Plan onderhoud zoals OPTIMIZE, zware refreshes en backfills ook alsof andere mensen bestaan. Want die bestaan.
Waarschuw op vroege signalen, niet pas op fouten
Als je eerste signaal een eindgebruiker is die klaagt, ben je al te laat.
Gebruik de Fabric Capacity Metrics-app voor het echte verhaal: throttling-status, burndown, timepoint-drillthrough en bijdrage per workspace. Gebruik monitoring op Azure-niveau als de tripwire die je aandacht trekt.
Je kunt bijvoorbeeld op de Fabric-capacityresource zelf alarmeren:
resource actionGroup 'Microsoft.Insights/actionGroups@2023-01-01' = {
name: 'ag-fabric-ops'
location: 'global'
properties: {
groupShortName: 'fabops'
emailReceivers: [
{
name: 'platform-team'
emailAddress: 'fabric-alerts@contoso.com'
}
]
}
}
resource alert 'Microsoft.Insights/metricAlerts@2018-03-01' = {
name: 'fabric-capacity-utilization-high'
location: 'global'
properties: {
scopes: [
fabricCapacity.id
]
severity: 2
enabled: true
evaluationFrequency: 'PT5M'
windowSize: 'PT15M'
criteria: {
allOf: [
{
name: 'high-capacity-utilization'
metricNamespace: 'Microsoft.Fabric/capacities'
metricName: 'CapacityUtilization'
operator: 'GreaterThan'
threshold: 85
timeAggregation: 'Average'
criterionType: 'StaticThresholdCriterion'
}
]
}
actions: [
{
actionGroupId: actionGroup.id
}
]
}
}
Zo'n alert vertelt je nog niet wat de precieze oorzaak is, maar het brengt je wel eerder in beweging dan de helpdesk. De root cause zul je nog steeds in de Capacity Metrics-app, je workspace-patronen en je workloadplanning moeten zoeken.
Veelgemaakte governance-fouten
Deze kom ik constant tegen:
Eén grote gedeelde capacity
Op papier goedkoop. In gebruikersfrustratie duur.
Alles krijgt mission critical
Als alles kritiek is, is niets kritiek. Je haalt je eigen stuurmechanisme weg.
Sizing op basis van daggemiddelden
Fabric-druk draait om vensters, carryforward en hersteltijd. Gemiddelden verstoppen alle drie.
Opschalen voordat je storage-layout klopt
Een versnipperde Delta table kan meer CU verspillen dan veel teams beseffen. Een grotere capacity geneest geen slechte file-layout.
Workspaces behandelen als mappen
In Fabric zijn het ook compute- en governancegrenzen. Ontwerp ze alsof dat ertoe doet, want dat doet het.
Tot slot
Fabric-capacity-governance gaat voor een groot deel over de vraag wie wie pijn mag doen.
Dat klinkt hard, maar het is wel de realiteit. Gedeelde compute betekent gedeelde gevolgen. De echte architectuurkeuze is niet of een F32 of F64 goedkoper is. De echte keuze is of één workspace, één refresh-keten of één notebookachterstand de rest van het platform mag verpesten.
Gebruik aparte capacities waar de blast radius dat rechtvaardigt. Gebruik workspace-level controls waar delen nog steeds logisch is. Los verspilling op voordat je een grotere SKU koopt. En als je dan opschaalt, doe het omdat de vraag echt is, niet omdat governance ontbrak.
Fabric is een goed platform voor gemengde analytics. Het is een slecht platform voor wensdenken.