When the system drive of an Exchange server fills up, transport applies back pressure and stops accepting mail, and services can start failing. Usually the space hasn't gone to mailboxes but to the diagnostic logging that Exchange and IIS write around the clock. In this post I'll show where that space goes, what you can delete safely, what you must never touch, and how to automate the cleanup so it doesn't come back.
How it works: where the space goes#
On a default installation everything below sits on the system drive, under %ExchangeInstallPath% (normally C:\Program Files\Microsoft\Exchange Server\V15\) and C:\inetpub:
| Location | What it holds | Who trims it |
|---|---|---|
C:\inetpub\logs\LogFiles\W3SVC1 and W3SVC2 | IIS request logs for the Default Web Site (client-facing) and the Exchange Back End site | Nobody: IIS rolls over to a new file but never deletes old ones |
%ExchangeInstallPath%Logging | Protocol and diagnostic logs (HttpProxy, MapiHttp, RpcHttp, EWS, Managed Availability and more) and the daily performance logs (.blg) under Logging\Diagnostics | Per-component limits only; nothing caps the folder as a whole |
%ExchangeInstallPath%Bin\Search\Ceres\Diagnostics\ETLTraces and \Logs | Trace (.etl) and text logs from the search components | Easy to overlook, and a frequent surprise on the system drive |
%ExchangeInstallPath%TransportRoles\Logs | Message tracking, connectivity and SMTP protocol logs | Exchange, by age and folder size |
Watch out: never delete database files (.edb), their transaction logs, checkpoint (.chk) or reserve (.jrs) files, or the transport queue database (mail.que) and its logs in TransportRoles\data\Queue. Those logs are also .log files, so a script that deletes *.log recursively is safe in the folders above and destructive if pointed at the install root or a database folder. Database logs are only removed by an Exchange-aware backup or circular logging; see transaction logs filling the disk.
Prerequisites#
- Local administrator rights and an elevated PowerShell window; the Exchange Management Shell is only needed for step 4.
- Your log-retention requirement. IIS and HttpProxy logs are what incident responders read after a compromise, so agree how many days you keep (or archive elsewhere) before you shorten anything.
Step-by-step cleanup#
1. Measure before you delete#
Get-Volume | Where-Object DriveLetter | Format-Table DriveLetter, @{n='FreeGB';e={[math]::Round($_.SizeRemaining/1GB,1)}}, @{n='SizeGB';e={[math]::Round($_.Size/1GB,1)}}
$ex = $env:ExchangeInstallPath
$folders = "$env:SystemDrive\inetpub\logs\LogFiles",
(Join-Path $ex 'Logging'),
(Join-Path $ex 'Bin\Search\Ceres\Diagnostics\ETLTraces'),
(Join-Path $ex 'Bin\Search\Ceres\Diagnostics\Logs'),
(Join-Path $ex 'TransportRoles\Logs')
foreach ($f in $folders) {
$sum = (Get-ChildItem $f -Recurse -File -ErrorAction SilentlyContinue | Measure-Object Length -Sum).Sum
'{0,8:N1} GB {1}' -f ($sum / 1GB), $f
}If Logging is the big one, size its subfolders the same way to see which component is responsible. One folder growing much faster than the rest often points to a component that is failing and logging the same error over and over.
2. Decide where IIS logs should live#
IIS logs are plain text and compress very well, so NTFS compression on the log folder is a cheap win. Better still, move them to a data volume: in IIS Manager › server › Logging, set Directory to a folder such as D:\IISLogs and click Apply. Update the cleanup script path below if you do.
3. Remove old IIS, diagnostic and search logs#
Save this as C:\Scripts\Remove-OldExchangeLogs.ps1. Without -Delete it only reports what it would remove:
param([int]$Days = 14, [switch]$Delete)
$ex = $env:ExchangeInstallPath
$targets = "$env:SystemDrive\inetpub\logs\LogFiles",
(Join-Path $ex 'Logging'),
(Join-Path $ex 'Bin\Search\Ceres\Diagnostics\ETLTraces'),
(Join-Path $ex 'Bin\Search\Ceres\Diagnostics\Logs')
$cutoff = (Get-Date).AddDays(-$Days)
foreach ($t in $targets) {
if (-not (Test-Path $t)) { Write-Warning "Not found: $t"; continue }
$old = Get-ChildItem $t -Recurse -File -Include *.log, *.blg, *.etl -ErrorAction SilentlyContinue |
Where-Object LastWriteTime -lt $cutoff
'{0,7} files {1,8:N2} GB {2}' -f $old.Count, (($old | Measure-Object Length -Sum).Sum / 1GB), $t
if ($Delete -and $old) { $old | Remove-Item -Force -ErrorAction SilentlyContinue }
}Run .\Remove-OldExchangeLogs.ps1 -Days 14, review the totals, then run it again with -Delete. Files that are still open are locked and simply skipped, and Exchange creates new files as it needs them. The transport logs are deliberately not in the list.
4. Let Exchange manage the transport logs#
Message tracking and protocol logs answer "where did that email go?", so set their limits instead of deleting files (details in message tracking with Get-MessageTrackingLog):
Get-TransportService EX01 | Format-List *LogMaxAge, *LogMaxDirectorySize, *LogPath
Set-TransportService EX01 -MessageTrackingLogMaxAge 30.00:00:00 -MessageTrackingLogMaxDirectorySize 2GB
Set-TransportService EX01 -MessageTrackingLogPath "D:\TransportLogs\MessageTracking"The connectivity and send/receive protocol logs have matching MaxAge, MaxDirectorySize and Path parameters, and Set-FrontendTransportService and Set-MailboxTransportService have equivalents for the logs of those services. Moving these logs off the system drive is the long-term fix.
5. Schedule it#
$action = New-ScheduledTaskAction -Execute 'powershell.exe' -Argument '-NoProfile -ExecutionPolicy Bypass -File C:\Scripts\Remove-OldExchangeLogs.ps1 -Days 14 -Delete'
$trigger = New-ScheduledTaskTrigger -Daily -At 2am
$princ = New-ScheduledTaskPrincipal -UserId 'SYSTEM' -LogonType ServiceAccount -RunLevel Highest
Register-ScheduledTask -TaskName 'Exchange log cleanup' -Action $action -Trigger $trigger -Principal $princVerify#
- Re-run the measurement from step 1: the cleaned folders now hold roughly your retention period's worth of files, and free space on the system drive has gone up.
- After the first scheduled run,
Get-ScheduledTaskInfo -TaskName 'Exchange log cleanup'shows a recentLastRunTimeand aLastTaskResultof0. Test-ServiceHealthreportsRequiredServicesRunning : Truefor every role, and new files keep appearing in the cleaned folders, which proves logging still works.- If the full disk had triggered back pressure, confirm that queues drain and mail flows again (see 452 4.3.1 back pressure).
Tips & gotchas#
- Don't switch logging off to save space. You lose the evidence you need for troubleshooting and security investigations; shorten retention or move the logs instead.
- Keep the target list explicit. Never widen the script to
%ExchangeInstallPath%as a whole, theMailboxfolder orTransportRoles\data. - Look for one-off space users too: extracted cumulative update files, old ISO images and memory dumps left behind after troubleshooting.
- If space disappears again quickly, find the folder that grew and the component behind it rather than shortening retention further.
- Size the system drive with headroom and keep databases, transaction logs and, ideally, the queue database on their own volumes.

