Repository navigation
The tempdb Space alert's percentage has no size floor, and on Azure SQL Database that makes it fire on one temp table #2515
Description
Found while removing the Azure SQL Database gate on TempDbStatsCollector (#2512). The collection is right and ships; this is the consequence downstream, and it is a policy call rather than a bug fix, so it is filed rather than folded in.
The mechanism
TempDbSpaceInfo.UsedPercent is
TotalReservedMb / (TotalReservedMb + UnallocatedMb) * 100and AlertEngine.CheckTempDbSpaceAsync fires when that clears TempDbSpaceThresholdPercent (default 80, in both SKUs).
Both halves of that denominator come from tempdb.sys.dm_db_file_space_usage, which reports the tempdb files as currently allocated. On a box with a pre-sized tempdb that denominator is effectively the ceiling, so the ratio is real headroom and the alert means what it says.
On Azure SQL Database it is not. The platform creates tempdb small and autogrows it toward the tier cap: 4 files, ~62 MB total on both 2-vCore tiers measured (GP_S_Gen5_2 and HS_S_Gen5_2, EngineEdition 5). So the ratio measures distance to the next autogrow, not distance to the ceiling.
The measurement
From #2512, on GP_S_Gen5_2, allocating ~57 MB into one #temp table:
total_reserved_mb |
unallocated_mb |
UsedPercent |
|
|---|---|---|---|
| idle | 1.88 | 60.69 | 3.0% |
after one #temp |
59.75 | 2.69 | 95.7% |
One ordinary temp table, and the server is over the 80% default with 60 MB at stake. That is not a tempdb running out of room; that is a tempdb that has not grown yet. Every Azure SQL Database target doing real work would page someone on its first busy minute.
The second threshold, failing the other way
FactScorer.ScoreTempDbVersionStore scores max_version_store_mb at absolute bars — >5000 MB CRITICAL, >2000 HIGH, >1000 MEDIUM — inherited from install/47_create_reporting_views.sql. Those are unreachable while tempdb is at its initial ~62 MB, so the arm scores 0.
This one is self-consistent (a >1 GB version store implies a >1 GB tempdb) and produces no false alerts, so it needs no change. It is worth knowing about anyway, because RCSI is on by default on Azure SQL Database, which makes the version store the tempdb consumer most likely to matter there — and the space-fraction arm is the only thing covering it until tempdb has grown past a gigabyte.
Options
- Size floor on the alert, mirroring
ScorePlanCacheBloat, which already solves exactly this shape:if (fact.Metadata.GetValueOrDefault("single_use_size_mb") < 100.0) return 0.0;— "a high % on a trivially small footprint is noise". Cheapest, platform-neutral, one constant. - Ceiling-aware denominator on Azure: compare against the tier's documented max tempdb data size instead of the current file size. Most correct, and the number is not in any DMV the collector reads today — it would need the service objective and a lookup table, which dates.
- Leave it, document it, let operators tune per fleet. Cheapest of all and the worst, because the default is what almost everyone runs.
What should decide it
Option 1 is the obvious move, and the whole question is the floor value — which is why this is not in #2512. It suppresses alerts existing on-prem and RDS targets get today, and I cannot measure what those customers rely on from here. Note that AlertEngineTests.TempDb_FiresAtThreshold_AndResolutionCarriesTheCurrentPercent uses a fixture totalling exactly 1000 MB, so a 1 GB floor flips an existing pin: the fixture is itself evidence that any floor silently redefines "small" for everyone.
The measurement that should settle it: the distribution of total_reserved_mb + unallocated_mb at the moment UsedPercent >= 80 across collected tempdb_stats history. If real on-prem fires cluster well above the candidate floor, the floor is free.
Whatever floor lands, it belongs on TempDbSpaceInfo next to UsedPercent so Lite and Darling cannot diverge — they share the type and the engine.
Activity
erikdarlingdata commentedon Aug 22, 2026
The ceiling is discoverable, so this is a denominator bug rather than a policy call. Probed the same
GP_S_Gen5_2live:tempdb.sys.database_filesmax_size(pages)The ROWS ceiling is 4 × 16 GB = 65,536 MB. Current allocation is 62.44 MB — a thousandth of it.
So the 57 MB
#tempthat reads as 95.7% full against the allocated size is 0.09% full against the cap the platform will actually let it grow to. The alert is not mistuned; it is measuring the wrong thing, and it happens to be nearly right on a box only because a pre-sized tempdb has already grown to its ceiling.What this changes
The fix is not a size floor. A floor would suppress a real Azure alert (a genuinely full 64 GB tempdb still reads small at the moment it starts growing) while still firing on the autogrow boundary, and — as noted here — any floor value silently redefines "small" for every existing on-prem and RDS target.
The fix is the denominator:
max_sizeis a real value, headroom isTotalReservedMb / SUM(max_size for ROWS files).-1), there is no ceiling to measure against and the current allocation is the only honest denominator — which is today's behaviour, so on-prem targets that grow without limit are unaffected.That makes
UsedPercentmean the same thing on every engine: distance to the point where tempdb cannot grow any further, which is the thing worth paging someone about. Today it means "distance to the next autogrow", which is worth paging nobody.It also removes the reason #2512 needed this caveat at all: with the right denominator, enabling Azure collection does not arm an alert that fires on the first busy minute.
Worth checking when implementing
dm_db_file_space_usagereports ROWS allocation, so mixing the log's cap into the denominator would understate usage. Confirm that against the collector's actual columns.max_sizewill start reporting a lower percentage than today wherever tempdb has not grown to its cap. That is a correction, not a regression, but it will move existing numbers and should be called out in the changelog.AlertEngineTests' fixture sits at exactly 1000 MB total; check whether it implies a cap.Merge pull request #2521 from erikdarlingdata/fix/2515-tempdb-ceiling…
Merge dev; take both meanings, and catch what merged cleanly and wrongly
Collect tempdb on Azure SQL Database: the gate's stated reason was false
Measure tempdb space against its ceiling, not its current allocation (e…