How to Configure DNS Aging and Scavenging on Windows Server 2012 R2

DNS aging and scavenging is the mechanism by which Windows Server DNS automatically removes stale resource records that are no longer valid. In Active Directory-integrated DNS environments using dynamic DNS updates, clients and servers register their records automatically when they obtain IP addresses. However, records are not always cleaned up when a machine is decommissioned, renamed, or changes networks. Over time, DNS zones accumulate thousands of orphaned records that increase query processing overhead, confuse administrators, and can lead to incorrect name resolution. This guide covers configuring and managing DNS aging and scavenging on Windows Server 2012 R2.

Prerequisites

The DNS Server role must be installed. Administrative rights on the DNS server are required. DNS zones must use dynamic updates (the scavenging feature only applies to dynamically registered records). The DnsServer module must be imported:

Import-Module DnsServer

# Verify DNS zones are configured for dynamic updates
Get-DnsServerZone | Where-Object {$_.ZoneType -eq "Primary"} |
    Select-Object ZoneName, DynamicUpdate, IsDsIntegrated

Understanding the Aging and Scavenging Workflow

Each dynamically registered DNS record has a timestamp indicating when it was last refreshed. The aging process uses two configurable intervals:

The No-Refresh Interval (default 7 days) is the period after the record is created or refreshed during which the record will not accept refresh updates. This reduces unnecessary zone replication traffic. The Refresh Interval (default 7 days) is the period after the no-refresh interval expires during which the record must be refreshed by the owner. If the record is refreshed within this window, the timestamp is updated and the cycle starts again. A record becomes eligible for scavenging after the no-refresh interval plus the refresh interval have both elapsed (total 14 days by default). The scavenging interval (default 7 days) determines how often the scavenging process runs to remove eligible stale records.

Enabling Aging and Scavenging on the DNS Server

Scavenging must be enabled at two levels: the server level (permits the server to perform scavenging) and the zone level (marks a zone for scavenging). Both must be enabled for scavenging to occur:

# Enable scavenging on the DNS server with default intervals
Set-DnsServerScavenging `
    -ScavengingState $true `
    -RefreshInterval "7.00:00:00" `
    -NoRefreshInterval "7.00:00:00" `
    -ScavengingInterval "7.00:00:00" `
    -ApplyOnAllZones $false

# View current server-level scavenging settings
Get-DnsServerScavenging

Enabling Aging on DNS Zones

After enabling server-level scavenging, enable aging on individual zones. The zone-level settings specify which refresh and no-refresh intervals apply to that zone’s records:

# Enable aging on the primary forward lookup zone
Set-DnsServerZoneAging `
    -Name "contoso.com" `
    -Aging $true `
    -RefreshInterval "7.00:00:00" `
    -NoRefreshInterval "7.00:00:00"

# Enable aging on the reverse lookup zone
Set-DnsServerZoneAging `
    -Name "10.168.192.in-addr.arpa" `
    -Aging $true `
    -RefreshInterval "7.00:00:00" `
    -NoRefreshInterval "7.00:00:00"

# Enable aging on all primary zones at once
Get-DnsServerZone | Where-Object {
    $_.ZoneType -eq "Primary" -and $_.DynamicUpdate -ne "None"
} | ForEach-Object {
    Set-DnsServerZoneAging -Name $_.ZoneName -Aging $true
    Write-Host "Aging enabled on: $($_.ZoneName)"
}

Verifying Zone Aging Configuration

# Check aging settings for a specific zone
Get-DnsServerZoneAging -Name "contoso.com"

# Check aging settings for all zones
Get-DnsServerZone | Where-Object {$_.ZoneType -eq "Primary"} |
    ForEach-Object {
        Get-DnsServerZoneAging -Name $_.ZoneName -ErrorAction SilentlyContinue
    } |
    Select-Object ZoneName, AgingEnabled, NoRefreshInterval, RefreshInterval

Reviewing Records Before Scavenging

Before enabling automatic scavenging, perform a manual review to understand how many records would be removed. The DNS Manager console provides a scavenging preview. Use PowerShell to identify records with old timestamps:

# Find DNS records with timestamps older than the combined no-refresh + refresh interval
$cutoffDate = (Get-Date).AddDays(-14)

Get-DnsServerResourceRecord -ZoneName "contoso.com" `
    -RRType A | Where-Object {
    $_.TimeStamp -ne $null -and
    $_.TimeStamp -lt $cutoffDate -and
    $_.TimeStamp -ne [DateTime]::MinValue
} | Select-Object HostName, RecordData, TimeStamp |
    Sort-Object TimeStamp |
    Export-Csv "C:ReportsStaleRecords.csv" -NoTypeInformation

# Count stale records
$staleCount = (Get-DnsServerResourceRecord -ZoneName "contoso.com" -RRType A |
    Where-Object {
        $_.TimeStamp -ne $null -and
        $_.TimeStamp -lt $cutoffDate
    }).Count
Write-Host "Records eligible for scavenging: $staleCount"

Running Manual Scavenging

Before relying on automatic scavenging, run a manual scavenge to observe the results. This is particularly useful the first time scavenging is enabled to get an initial cleanup without waiting for the scheduled interval:

# Start an immediate scavenge on a specific DNS server
Start-DnsServerScavenging -ComputerName "DC-LON-01" -Confirm:$false

# Monitor the scavenging event in the DNS Server event log
Get-WinEvent -LogName "DNS Server" |
    Where-Object {$_.Id -in @(2501,2502,2503)} |
    Select-Object TimeCreated, Id, Message | Format-List

DNS scavenging events: Event 2501 (scavenging has begun), Event 2502 (scavenging completed successfully with count of records removed), Event 2503 (scavenging encountered an error).

Protecting Static Records from Scavenging

Static records (those with a timestamp of 0) are never scavenged. Any record you want to keep permanently should have its timestamp cleared:

# View a record's timestamp
Get-DnsServerResourceRecord -ZoneName "contoso.com" -Name "webserver01" -RRType A |
    Select-Object HostName, RecordData, TimeStamp

# Make a record static (remove timestamp) to prevent scavenging
$record = Get-DnsServerResourceRecord -ZoneName "contoso.com" -Name "webserver01" -RRType A
$newRecord = [ciminstance]$record.Clone()
$newRecord.TimeToLive = [System.TimeSpan]::FromHours(1)
$newRecord.TimeStamp = $null  # Setting to null makes it static
Set-DnsServerResourceRecord -ZoneName "contoso.com" -OldInputObject $record -NewInputObject $newRecord

Configuring Scavenging Across Multiple DNS Servers

# Apply scavenging settings to all DNS servers in the domain
$dnsServers = (Get-ADDomainController -Filter *).HostName
foreach ($server in $dnsServers) {
    Set-DnsServerScavenging `
        -ComputerName $server `
        -ScavengingState $true `
        -RefreshInterval "7.00:00:00" `
        -NoRefreshInterval "7.00:00:00" `
        -ScavengingInterval "7.00:00:00"
    Write-Host "Scavenging configured on: $server"
}

Summary

DNS aging and scavenging on Windows Server 2012 R2 is essential maintenance for dynamic DNS environments. Without scavenging, DNS zones accumulate stale records indefinitely, degrading performance and reliability. The default intervals of 7-day no-refresh and 7-day refresh with a 7-day scavenge interval are appropriate for most environments. Before enabling automatic scavenging, audit existing stale records, protect critical static records by clearing their timestamps, and run a manual scavenge to establish a clean baseline. Monitor the DNS Server event log after enabling automatic scavenging to confirm the expected number of records are being removed and no legitimate records are incorrectly targeted.