Helpdesk: "RDP to FIN-LT-114 keeps connecting to the wrong laptop and failing with a logon error. nslookup for the Finance print server returns three addresses, and two of them belong to laptops that were reimaged in the spring. Somebody turned on scavenging on the zone last year and it's 'not working'. A forum post says to run dnscmd /ageallrecords on the zone and set the refresh intervals to one hour on every domain controller. Can we just do that?"
Not yet. Scavenging isn't one switch. A record is only deleted when four things are true at once, on the server doing the scavenging: scavenging is on for that server, aging is on for the zone, the record carries a timestamp, and that timestamp is older than the no-refresh plus refresh intervals. Microsoft's own list: "Scavenging removes a record only when it meets all four of the following conditions". And the reason nothing happens when only half of it is set: "Aging alone never deletes records; it only tracks timestamps." dnscmd /ageallrecords stamps every record in the zone, including the static ones you meant to keep, and Microsoft says that stamp "can't be reversed." One-hour intervals on every DC turn a slow cleanup into a fast one that can delete live records. Work through it as a chain: which records, in which zone, since when → is scavenging on for a server, and which one? → is aging on for the zone, and is the zone eligible yet? → do the stale records have a timestamp at all? → what do events 2501 / 2502 and the audit log say happened? → is something still refreshing the "stale" record (a client, DHCP, a second NIC)? → for AD-integrated zones: has the partition replicated, and which server is allowed to scavenge? → the reverse problem: scavenging deleting live records. Get-DnsServerScavenging, Get-DnsServerZoneAging, dnscmd /zoneinfo, Get-DnsServerResourceRecord, Get-WinEvent, and Get-DhcpServerv4DnsSetting are the sources for that chain. Stamp every record and shorten every interval on a broken chain, and you've traded stale records for missing ones.
If the stale record showed up as AD replication failing with error 1722 because a DC's A record points at an old address, read Active Directory Replication Error 1722 first; fix that one record there, then come back for the cleanup. If clients aren't getting addresses at all, start with Windows Server DHCP Not Assigning IP Addresses. This post covers "Stale A or PTR records stay in a Windows Server DNS zone (usually AD-integrated) after aging and scavenging were supposedly enabled, or scavenging ran and removed records it shouldn't have, and you need a read-first path before you stamp records, shorten intervals, or turn scavenging on everywhere."
TL;DR
- Check all three levels: server, zone, record. Microsoft: "For scavenging to take effect, it must be configured on three levels: record, zone, and server." Server-level scavenging doesn't replicate; zone aging does (Steps 2-4).
-
A scavenging interval of 0 means off. On
Set-DnsServerScavenging, Microsoft: "The default setting is 0, which disables scavenging for the DNS server." Read it on every DNS server, not only the one you remember configuring (Step 2). - Static records never age. "The timestamp of static records is 0, indicating they aren't scavenged." Records created before aging was turned on may carry no timestamp either (Step 4).
- Event 2502 isn't always "all clean". Its message: "The DNS server has completed a scavenging cycle but no nodes were visited," and the first cause Microsoft lists is "No zones are configured for scavenging by this server." (Step 5).
-
A zone can name a scavenging server that no longer exists. Then the cycle runs and deletes nothing.
dnscmd /zoneinfoshows the list;dnscmd /zoneresetscavengeserverschanges it (Steps 3, 9). - Defaults are slow on purpose. With 7-day intervals and a 7-day scavenging period, Microsoft says a stale record can stay "up to 21 days with all defaults." Patience is part of the fix.
Where in the chain did it break?
| Step | What should be true | Typical symptom when it breaks |
|---|---|---|
| 1. Symptom captured | Which records, which zone, which servers, since when, what changed | "DNS is full of junk" with no record name |
| 2. Server scavenging | One DNS server per zone has scavenging on, with a nonzero interval | Interval 0 everywhere; or on every DC with different schedules |
| 3. Zone aging | Aging on for the zone; zone eligible; this server allowed to scavenge it | Aging off; "can be scavenged after" in the future; scavenge server list names a dead DC |
| 4. Record timestamp | Stale records carry a nonzero timestamp older than both intervals | Old records with timestamp 0 (static) |
| 5. Events | 2501 or 2502 read on the scavenging server; audit 521 shows what was deleted | 2502 "no nodes were visited"; no 2501/2502 at all |
| 6. Refresh source | Nothing still refreshes the stale name | A client on VPN, a second NIC, or DHCP keeps it fresh; DHCP owns the record |
| 7. AD replication | The zone's partition has replicated since the DNS service started | No 2501/2502 events; servers disagree on the record |
| 8. Over-deletion | Intervals at least as long as the longest refresh period | Live servers lose records every few days |
| 9. Change | Only after Steps 1-8 agree: one link, one change |
/ageallrecords on the zone, same problem plus static records at risk |
Step 1: Capture the symptom (read-only)
Write these on the ticket first:
| Fact | Why it matters |
|---|---|
| Two or three record names that should be gone (and their timestamps) | You'll trace these exact records through every step (our habit) |
| Zone name and type (forward or reverse, AD-integrated or file-backed) | Aging is per zone. "Secondary and stub zones don't support these processes." |
| Every DNS server that hosts the zone | Server-level scavenging is set per server and doesn't replicate |
| When scavenging was "turned on", and by whom | A recent change may still be inside its first refresh interval (Step 3) |
| What changed | DC retired, DNS role moved, zone converted to AD-integrated, DHCP lease or scope changes, DHCP failover added |
| The opposite symptom? | Records for live machines disappearing is a different branch (Step 8) |
Then branch on what you see:
| What you see | What it usually means (our reading unless noted) | Start at |
|---|---|---|
| No 2501 or 2502 events on any server | No server is scavenging, or the zone's partition hasn't replicated | Steps 2, 7 |
| 2502 every cycle on the server you configured | Microsoft's first cause: "No zones are configured for scavenging by this server." | Step 3 |
| 2501 runs, the old records survive | Records without a timestamp, or a different server is the only one allowed to scavenge | Steps 3, 4 |
| Old records with a recent timestamp | Something still refreshes them | Step 6 |
| Two names on one IP address | Lease reused before the old record aged out (Microsoft's DHCP lease blog) | Step 6 |
| Records for live servers vanish | Intervals shorter than the refresh period, or stamped static records | Step 8 |
Step 2: Is scavenging on for a server, and which one? (read-only)
Server-level scavenging is a property of each DNS server, not of the zone. Microsoft's configuration page: "This setting doesn't replicate, so configure it individually on every server that needs to scavenge." Read it on every DNS server that hosts the zone. nltest /dclist: lists the DCs (Microsoft uses it in its scavenging article):
:: Read-only. List the domain controllers (contoso.com is an example domain)
nltest /dclist:contoso.com
:: Read-only. One server-level setting from the registry (Microsoft's /info syntax; DC01 is an example)
dnscmd DC01 /info /scavenginginterval
# Read-only. Server-level aging and scavenging settings on each DNS server (server names are examples; the loop is our form)
foreach ($dc in 'DC01', 'DC02', 'DC03') {
"=== $dc"
Get-DnsServerScavenging -ComputerName $dc | Format-List *
}
Read ScavengingInterval first. Microsoft on that parameter: it "determines whether the scavenging feature for the DNS server is enabled and sets the number of hours between scavenging cycles." And: "The default setting is 0, which disables scavenging for the DNS server." The dnscmd page says the same for /scavenginginterval: "The default setting is 0x0, which disables scavenging for the DNS server." ScavengingState is a different thing; its parameter page says it "determines whether the DNS scavenging feature is enabled by default on newly created zones." The output also shows a last-scavenge time on the builds we've seen; the cmdlet page doesn't document the output fields, so read the Format-List * output rather than trusting a property name (our note).
How many servers should scavenge? Microsoft: "Enable server-level scavenging on only one DNS server per zone." And on why one is enough: "Only one server is required to scavenge since the zone data is replicated to all servers hosting the zone." Microsoft's dynamic update troubleshooting guide adds where to put it: "The scavenging cycle is a low-priority thread of the DNS process, so it might not always run consistently." Its advice: "Ideally, scavenging should be set up on a DC without any FSMO roles."
| Finding | What it means (Microsoft unless noted) | Next |
|---|---|---|
| Interval 0 on every server | Nobody scavenges. Zone aging alone deletes nothing | Step 9: one server |
| Nonzero on one server | Expected | Step 3: is that server allowed to scavenge the zone? |
| Nonzero on several servers | Works, but "Scavenging events and audit data spread across multiple servers." | Read events on each (Step 5); reduce to one (Step 9) |
| Nonzero only on a retired or PDC emulator DC | Retired: nobody scavenges. PDC: low-priority thread on a busy DC | Step 9: move it to a DC without FSMO roles |
| Interval very short (hours) | Not a cause of "not working"; a cause of surprises later (our reading) | Step 8 |
Step 3: Is aging on for the zone, and is the zone eligible yet? (read-only)
Aging is the zone half. For AD-integrated zones it replicates with the zone: "For an AD-integrated zone, enable aging once and the setting replicates with the zone data to other DNS servers that host the zone." Microsoft also says the zone setting wins over the server-wide default: "The zone-level aging has higher precedence." Read both the PowerShell view and the registry view on the server that should scavenge:
# Read-only. Zone type and aging settings for one zone on the scavenging server (zone and server names are examples)
Get-DnsServerZone -Name 'contoso.com' -ComputerName DC02 | Format-List *
Get-DnsServerZoneAging -Name 'contoso.com' -ComputerName DC02 | Format-List *
# Read-only. Every zone's aging state on that server, including reverse zones (the loop is our form)
Get-DnsServerZone -ComputerName DC02 | Where-Object { -not $_.IsAutoCreated } | ForEach-Object {
Get-DnsServerZoneAging -Name $_.ZoneName -ComputerName DC02 -ErrorAction SilentlyContinue
} | Format-Table -AutoSize
:: Read-only. The zone's registry view: aging, refresh / no refresh (hours), scavenge available, and the Scavenge Servers list
dnscmd DC02 /zoneinfo contoso.com
Microsoft's article on records that never get deleted (KB 2791165) uses exactly that dnscmd /zoneinfo output. Its sample shows aging = 1, refresh interval = 168, no refresh = 168, and a Scavenge Servers entry with one address. Its explanation of that address: "It's the IP address of the server that has the permission to scavenge the zone (Most likely this could be a server that is no longer existing)". The cause it gives: the zone "was previously configured manually for scavenging by a different server (using dnscmd), then scavenging was disabled in the environment and then enabled again on another server." Set-DnsServerZoneAging describes the default when that list is empty: "If you do not specify any scavenge servers, any primary DNS server that is authoritative for the zone can scavenge."
The zone's own waiting period. When aging is turned on, the zone isn't eligible right away. Microsoft: "When you first enable aging on a zone, the zone gets one refresh interval of protection from scavenging." The DNS console shows it as The zone can be scavenged after in the zone's Aging dialog; Microsoft's note if it's missing: "If you don't see The zone can be scavenged after timestamp, reload the zone." The clock also resets. Microsoft's list of events that reset it includes "You enable dynamic updates for the zone." and "The DNS Server service starts and loads a scavenging-enabled primary zone." So a DNS server that restarts often, or a zone whose settings someone keeps toggling, can keep pushing the first cleanup out (our reading).
Why a zone gets skipped. Microsoft's list of reasons a scavenging pass skips a zone:
| Microsoft's skip reason | Read-only check |
|---|---|
| "The server isn't an authorized scavenging server for the zone." | Scavenge Servers in dnscmd /zoneinfo; the scavenge-servers audit event (Step 5) |
| "Aging is disabled on the zone." |
Get-DnsServerZoneAging (AgingEnabled is the alias Microsoft lists for -Aging) |
| "The current server time is earlier than the zone's available for scavenging time." |
scavenge available in /zoneinfo, or the console's "can be scavenged after" |
| "The zone is paused, a cache zone, or an offline-signed zone." |
Get-DnsServerZone output |
| "The zone's Active Directory directory partition hasn't replicated since the DNS server started." | Step 7 |
| Finding | What it means (Microsoft unless noted) | Next |
|---|---|---|
| Aging off on the zone (or only on the forward zone) | Scavenging skips the zone. Reverse zones are separate zones with their own aging (our reading) | Step 9: enable aging on that zone |
| "Set Aging/Scavenging for All Zones" used without the checkbox | "Without this option, new settings apply only to zones created afterward." | Step 9 |
| Scavenge Servers lists an address that isn't this server | Only that server may scavenge; if it's gone, nobody does | Step 9: /zoneresetscavengeservers
|
| The zone's "can be scavenged after" time is in the future | Inside the first refresh interval, or reset by a restart | Wait, then Step 5 |
| Secondary or stub zone | Not supported; scavenge on the primary or AD-integrated copy | The zone's primary server |
Step 4: Do the stale records have a timestamp? (read-only)
Microsoft: "The timestamp of static records is 0, indicating they aren't scavenged." That covers every record someone created by hand in the console or with Add-DnsServerResourceRecordA without -AgeRecord. Microsoft's dynamic update troubleshooting guide adds a less obvious group: "If you recently enabled the given option, the records that were registered before the change won't carry a timestamp or be scavenged." And the dnscmd page lists record types that never take part: "Name server (NS) resource records, start of authority (SOA) resource records, and Windows Internet Name Service (WINS) resource records aren't included in the scavenging process".
Read the records you wrote down in Step 1, then count static versus timestamped records in the zone:
# Read-only. The Step 1 records with their timestamps (static records show a zero or empty Timestamp; the RecordData.IPv4Address filter is our form)
Get-DnsServerResourceRecord -ZoneName 'contoso.com' -Name 'FIN-LT-114' -ComputerName DC02
Get-DnsServerResourceRecord -ZoneName 'contoso.com' -RRType 'A' -ComputerName DC02 |
Where-Object { $_.RecordData.IPv4Address -eq '10.20.30.41' } | Select-Object HostName, Timestamp, TimeToLive
# Read-only. How many A records are static vs timestamped (the grouping is our form)
Get-DnsServerResourceRecord -ZoneName 'contoso.com' -RRType 'A' -ComputerName DC02 |
Group-Object { if ($_.Timestamp) { 'Timestamped' } else { 'Static (no timestamp)' } } | Select-Object Name, Count
Then list the records that are already past both intervals, which is what Microsoft's setup guide tells you to look at before any cleanup ("Look for any records older than the Refresh plus No-Refresh interval in your DNS records."):
# Read-only. Timestamped A records older than no-refresh + refresh (interval property names follow the -NoRefreshInterval / -RefreshInterval parameters; the filter is our form)
$aging = Get-DnsServerZoneAging -Name 'contoso.com' -ComputerName DC02
$cutoff = (Get-Date) - ($aging.NoRefreshInterval + $aging.RefreshInterval)
Get-DnsServerResourceRecord -ZoneName 'contoso.com' -RRType 'A' -ComputerName DC02 |
Where-Object { $_.Timestamp -and $_.Timestamp -lt $cutoff } |
Select-Object HostName, Timestamp, @{ n = 'IPv4'; e = { $_.RecordData.IPv4Address } } | Sort-Object Timestamp
Run it on the scavenging server. Timestamps only replicate once aging is on. A community-written TechNet Wiki article archived on Microsoft Learn puts it this way: "when DNS aging and scavenging is disabled on an AD-integrated DNS zone, the timestamps of resource records on your DC/DNS servers are not consistent". Microsoft's setup article says the same in its own words.
| Finding | What it means (Microsoft unless noted) | Next |
|---|---|---|
| Stale record shows timestamp 0 | Static: never scavenged | Delete it deliberately, or stamp it (Step 9) |
| Many old records are static, created before aging was on | Microsoft's "registered before the change" note | Step 9: one node or one record at a time, not /ageallrecords
|
| Record past both intervals, nonzero timestamp | It should go on the next eligible pass | Step 5: did a pass run on an authorized server? |
| Record has a recent timestamp but the machine is gone | Something is still refreshing it | Step 6 |
Step 5: What do the scavenging events say? (read-only)
After each pass the scavenging server logs one of two events in its DNS Server log. Event 2501's message starts "The DNS server has completed a scavenging cycle" and lists visited zones, visited nodes, scavenged nodes, and scavenged records, then "The next scavenging cycle is scheduled to run in %6 hours." Event 2502 reads "The DNS server has completed a scavenging cycle but no nodes were visited." Its listed causes start with "1) No zones are configured for scavenging by this server." Microsoft's newer configuration page calls 2502 "the normal, healthy state when all records are current", so read it with Step 3's findings next to it (our reading).
Microsoft's configuration page adds three AD-integrated zone events that block scavenging: 4013 (waiting for AD DS), 4515 (duplicate zone in AD), and 4521 (zone couldn't load). The Audit channel (on by default, per Microsoft: "DNS audit logs are enabled by default") shows the detail: 521 for each scavenged record, 552 for a cycle start, 554 for a cycle that was terminated, and 567 for a change to the scavenge servers.
# Read-only. The DNS log names on this server (list first; the exact names below are our form)
Get-WinEvent -ListLog '*DNS*' -ErrorAction SilentlyContinue | Select-Object LogName, RecordCount, IsEnabled
# Read-only. On the scavenging server: last 30 days of scavenging and zone-load events in the DNS Server log
Get-WinEvent -FilterHashtable @{ LogName = 'DNS Server'; Id = 2501, 2502, 4013, 4515, 4521; StartTime = (Get-Date).AddDays(-30) } -ErrorAction SilentlyContinue |
Select-Object TimeCreated, Id, Message | Format-List
# Read-only. The audit view: records scavenged (521), cycle start / termination (552 / 554), scavenge servers (567)
Get-WinEvent -FilterHashtable @{ LogName = 'Microsoft-Windows-DNSServer/Audit'; Id = 521, 552, 554, 567; StartTime = (Get-Date).AddDays(-30) } -ErrorAction SilentlyContinue |
Select-Object TimeCreated, Id, Message | Format-List
The 521 message is the one to search for a name you care about: "A resource record of type %1, name %2, TTL %3 and RDATA %5 was scavenged from scope %7 of zone %6." The 567 message names who may scavenge: "Only %2 can run scavenging." Microsoft's note on the audit log: it's "local to the given DNS server", so read it on the server that scavenged.
When will the next pass run? Microsoft's setup article: "By getting the timestamp on the most recent Event ID 2501 or 2502 and adding the scavenging period to it, you can tell exactly when a server will attempt to scavenge." Its newer page softens that: it "gives an estimate, but the event time reflects completion of the pass rather than its start time." And the period restarts with the service: "It resets whenever the DNS service restarts."
| Finding | What it means (Microsoft unless noted) | Next |
|---|---|---|
| No 2501 / 2502 on any server | No server scavenging, or the zone isn't available (Microsoft's replication scenario) | Steps 2, 7 |
| 2502 on the configured server, every cycle | No zone this server may scavenge, or nothing eligible yet | Step 3 |
2501 with Scavenged Records above 0, Step 1 records survive |
Those records aren't eligible: no timestamp, or still refreshing | Steps 4, 6 |
| 4013 / 4515 / 4521 | Zone loading or AD problems block scavenging | Fix the zone load first; Active Directory Replication Error 1722 for the replication side |
| 521 names a record you needed | Over-deletion | Step 8 |
Step 6: Is something still refreshing the "stale" record? (read-only)
A record that keeps a fresh timestamp isn't stale, whatever the CMDB says. Microsoft's refresh rules: "Windows clients dynamically update DNS every 24 hours." For statically addressed machines: "Clients also update every 24 hours to refresh records in the DNS database." So a laptop that's still on the VPN, a reimaged machine that kept its name, or a second adapter registering an extra address all keep their records alive (our reading of those rules).
Who owns the record. In a secure-only AD-integrated zone, ownership decides who can update or delete a record. Microsoft: "When a DHCP server performs a secure dynamic update on a name, it becomes the owner of that name. Only that DHCP server can update any record for that name." Its older DnsUpdateProxy article describes how that leaves stale records behind: "The DNS server can end up with stale resource records when a DHCP server is configured to dynamically register host (A) and pointer (PTR) resource records on behalf of DHCP clients using dynamic update." Microsoft's setup article puts the owner check in its sanity phase: "Who is the owner of the record (see the Security tab in the record properties)?" The same check from PowerShell:
# Read-only. Owner and tombstone state of one dnsNode in an AD-integrated zone (zone DN format from Microsoft's /zoneinfo sample; the AD: drive form is ours)
Import-Module ActiveDirectory
$zoneDN = 'DC=contoso.com,CN=MicrosoftDNS,DC=DomainDnsZones,DC=contoso,DC=com'
$node = "DC=FIN-LT-114,$zoneDN"
(Get-Acl -Path "AD:\$node").Owner
Get-ADObject -Identity $node -Properties dNSTombstoned, whenChanged | Select-Object Name, dNSTombstoned, whenChanged
What DHCP is doing. If DHCP registers records for clients, read its DNS settings for the scope. Microsoft on Get-DhcpServerv4DnsSetting: "This cmdlet gets the effective DNS setting at the specified level such as reservation, scope, or server."
# Read-only. DHCP's DNS update settings for one scope, its leases, and the DNS update account (server and scope are examples)
Get-DhcpServerv4DnsSetting -ComputerName 'dhcp01.contoso.com' -ScopeId 10.20.30.0
Get-DhcpServerv4Scope -ComputerName 'dhcp01.contoso.com' -ScopeId 10.20.30.0 | Format-List *
Get-DhcpServerv4Lease -ComputerName 'dhcp01.contoso.com' -ScopeId 10.20.30.0 -AllLeases |
Where-Object IPAddress -eq '10.20.30.41'
Get-DhcpServerDnsCredential -ComputerName 'dhcp01.contoso.com'
The fields to read mirror the Set-DhcpServerv4DnsSetting parameters (our reading): DynamicUpdates ("Always", "Never", or "OnClientRequest"), DeleteDnsRROnLeaseExpiry ("Specifies that the DHCP server service should delete the DNS resource records for the client after the lease expires."), and NameProtection. The scope's lease duration is in the Format-List * output.
The lease and the intervals. Microsoft's DHCP lease blog walks through the classic failure: an 8-day lease, 7 + 7 day intervals, the lease expires, the address goes to a new client, and the old record stays: "Client-A is the owner of its DNS record so it cannot be deleted by the DHCP server (by default)." Now two names resolve to one address, and Kerberos to the wrong machine fails, which is the Helpdesk ticket above. Microsoft's two current pages don't agree on which way to size this. The scavenging troubleshooting article: "Refresh + No-refresh >= The maximum DHCP lease". The configuration article's common mistakes: "Align the combined No-refresh and Refresh intervals with your DHCP lease duration so that the combined interval is equal to or less than the lease." Our reading: "greater than or equal" protects live clients from deletion, and "equal to or less" clears reused addresses sooner. The blog lists both options with their trade-offs. Pick one on purpose.
| Finding | What it means (Microsoft unless noted) | Next |
|---|---|---|
| Timestamp keeps moving on a "retired" name | Something still registers it: a live device, a second NIC, or a reimaged machine with the same name (our reading) | Find the device, not the record |
| Owner is a DHCP server's computer account | Only that DHCP server can update or delete it | Step 9: DHCP credentials, lease expiry deletion, or let scavenging remove it |
DeleteDnsRROnLeaseExpiry false where DHCP registers records |
Expired leases leave their records behind (our reading) | Step 9 |
| Two names on one IP, lease shorter than both intervals | Microsoft's lease blog scenario | Step 9: intervals vs lease, chosen deliberately |
| Machine in Azure | "Azure machines have a lease of 136 years." Their DHCP refresh never comes | Microsoft's Registration Refresh Interval policy (Step 8) |
Step 7: AD-integrated zones: replication and which server's copy (read-only)
In an AD-integrated zone, deletions travel by AD replication, and Microsoft protects against a server that's been out of touch. From its troubleshooting article, for the case where scavenging doesn't occur and events 2501 and 2502 aren't generated: "verify that the zone is available for scavenging by ensuring that the partition (where the zone is stored) has replicated since the system boot." Its rule: "If the partition hasn't fully synced with at least one replication partner in the last zone refresh interval, don't scavenge the zone." The scenario it describes is a DC whose replication partner is being decommissioned. Its fix, if that DC isn't needed: remove it.
Microsoft also says replication isn't a substitute for scavenging: "Active Directory replication alone doesn't remove stale records, so you still need these features on integrated zones."
Compare what each DNS server answers and check replication, using the reads Microsoft's configuration page names:
# Read-only. Ask each DNS server directly for the same name, DNS only (server names are examples; the loop is our form)
foreach ($dns in 'DC01', 'DC02', 'DC03') {
Resolve-DnsName -Name 'FIN-LT-114.contoso.com' -Server $dns -DnsOnly -ErrorAction SilentlyContinue |
Select-Object @{ n = 'Server'; e = { $dns } }, Name, Type, IPAddress
}
:: Read-only. Replication health, then one DC's inbound partners (Microsoft's configuration page names both commands; the DC argument is our form)
repadmin /replsummary
repadmin /showrepl DC02
Microsoft's caution when servers seem to disagree: "Cached responses can persist in a client's cache or in a non-authoritative server's cache after replication finishes, so a stale cached response doesn't necessarily indicate a replication failure." Query the authoritative servers, not a client (our reading of that note).
A scavenged record isn't removed from AD at once. The TechNet Wiki article: "the resource record dNSTombstoned attribute will be set to TRUE on its AD object when it is scavenged." Step 6's Get-ADObject read shows it.
| Finding | What it means (Microsoft unless noted) | Next |
|---|---|---|
| Replication failures on the scavenging DC | The zone isn't available to scavenge, by design | Active Directory Replication Error 1722, then Step 5 again |
| A decommissioned DC still listed | Microsoft's scenario for missing 2501/2502 | Finish the decommission; nltest /dclist: to confirm |
| Servers answer differently, replication healthy | Caching, or the record is in a different partition or zone (our reading) | Check the zone's replication scope in Get-DnsServerZone
|
dNSTombstoned true on a record that still resolves somewhere |
A server or cache is behind (our reading) | Replication, then client cache |
Step 8: The opposite problem: scavenging deleting live records (read-only)
Microsoft's DNS troubleshooting guide: "If DNS records go missing from DNS zones, scavenging is the most common cause." Its example: "if these values are both less than 24 hours, you lose DNS records." The scavenging article walks through the same case with 2-hour intervals and a server that refreshes every 24 hours: "The cause is that the Refresh + No-refresh interval is less than 24 hours." Microsoft's older aging guide gives the rule for the refresh interval: "it is important that the length of time used be greater than the maximum possible refresh period for any resource records that are contained in the zone." Its table puts the DHCP server's refresh at "Four days (half of the lease interval, which is eight days by default)."
The other ways live records go, each from the Microsoft page named:
| Cause | Microsoft's text | Read-only check |
|---|---|---|
dnscmd /ageallrecords on the zone |
It sets a timestamp "for all records in the zone, including static records that you don't want to be scavenged." | Static servers and printers with nonzero timestamps (Step 4) |
| A static record that was dynamic | "DDNS can cause a static record to be deleted from DNS if that record is registered as a dynamic record and then converted to a static record by removing its timestamp." | Who has delete rights on the record (Step 6 owner read) |
| Updates failing, so records age out | "The DNS Dynamic Update Protocol update to existing records fails. Because of this issue, the DNS scavenging process considers the records to be aged, and it deletes them." | Registration failure events in the System log on clients, DCs (Netlogon), and DHCP servers |
| DHCP on a DC without credentials | The guide: "This can cause issues like the unintended scavenging of static records." |
Get-DhcpServerDnsCredential on that DC (Step 6) |
| Azure VMs | Their 136-year lease means no DHCP refresh | Computer Configuration\Administrative Templates\Network\DNS Client\Registration Refresh Interval |
For the Azure case, Microsoft's fix is that policy, which "maps to the registry key" HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows NT\DNSClient, with the note "To make the changes to this value effective, you must restart Windows."
If the over-deletion is happening now, stop the scavenging server first (Step 9, interval 0), then get the records back by re-registering the clients or re-creating them from your export. Microsoft says the Export-DnsServerZone file is for troubleshooting and "is not in the same format as a file-backed zonefile", so treat it as a reference list, not a one-step restore (our reading). Find the cause after (our habit).
Common false starts (read these before you change anything)
| False start | Why it hurts | Read-first alternative |
|---|---|---|
dnscmd /ageallrecords on the whole zone |
Stamps static records too, and "A time stamp added by using the ageallrecords command can't be reversed." | Stamp one node, or tick Delete this record when it becomes stale on one record (Step 9) |
Set-DnsServerResourceRecordAging -Recurse on the zone |
Same effect from PowerShell: it "sets a time stamp to the current time for records" in the zone | Step 4's list first; stamp only what should age |
| Scavenging on every DC | Microsoft recommends one per zone; with many, deletions are harder to trace | One server without FSMO roles (Step 2) |
| Intervals cut to hours | Records for machines that refresh every 24 hours get deleted (Step 8) | Size intervals to the longest refresh period and the DHCP lease (Step 6) |
| Expecting a manual scavenge to clean up today | "Note that manual attempts won't bypass the safety valves." | Read "can be scavenged after" and the record timestamps first (Steps 3, 4) |
| Bulk-deleting old records by hand | Records for live clients come back, or don't, depending on ownership (our reading) | Microsoft's sanity check: "Don't proceed unless you can explain any outdated records." |
Step 9: Change one link, then prove it (only after the read)
Pick the one change Steps 1-8 point at. Save the current state first. Microsoft's best practices: "Back up your zone data. Export zone data before you enable aging or trigger scavenging."
# Low-risk write. Export the zone and save the current settings (the file lands in C:\Windows\System32\dns by default; the redirections are our habit)
New-Item -Path C:\Temp -ItemType Directory -Force | Out-Null
Export-DnsServerZone -Name 'contoso.com' -FileName 'contoso.com.before-scavenging.txt' -ComputerName DC02
Get-DnsServerScavenging -ComputerName DC02 | Format-List * > C:\Temp\scavenging-before.txt
Get-DnsServerZoneAging -Name 'contoso.com' -ComputerName DC02 | Format-List * > C:\Temp\zoneaging-before.txt
Server scavenging on one server (Step 2). Turn it on where you want it and off where you don't. The interval form is Microsoft's (dd.hh:mm:ss; 0 disables):
# Change. Dry-run first: scavenging on DC02 every 7 days, off on DC01 (server names are examples)
Set-DnsServerScavenging -ComputerName DC02 -ScavengingState $true -ScavengingInterval 7.00:00:00 -WhatIf
Set-DnsServerScavenging -ComputerName DC01 -ScavengingInterval 0.00:00:00 -WhatIf
Leave -ApplyOnAllZones off unless you mean it. Microsoft: it's "the PowerShell equivalent of the DNS Manager Apply these settings to the existing Active Directory-integrated zones option".
Zone aging and who may scavenge (Step 3). Microsoft's form, with the scavenging server's address (an example):
# Change. Dry-run first: aging on for the zone with 7 + 7 day intervals, and only 192.0.2.12 (DC02) may scavenge it
Set-DnsServerZoneAging -Name 'contoso.com' -ComputerName DC02 -Aging $true -NoRefreshInterval 7.00:00:00 -RefreshInterval 7.00:00:00 -ScavengeServers 192.0.2.12 -WhatIf
If /zoneinfo named a dead server, Microsoft's KB 2791165 fix is dnscmd. Its other form, without an address, "resets all scavenging server settings and removes manually specified servers":
:: Change. Allow only DC02 (192.0.2.12) to scavenge contoso.com, then read it back
dnscmd DC02 /zoneresetscavengeservers contoso.com 192.0.2.12
dnscmd DC02 /zoneinfo contoso.com
Remember the clock: changing aging resets the zone's available-for-scavenging time, so the first pass after this change is at least one refresh interval away (Step 3).
Records without a timestamp (Step 4). For one record: open it with View > Advanced on, tick Delete this record when it becomes stale, and apply. Microsoft: "the current time is rounded down to the nearest hour and applied as the timestamp on the record." For one name with all its records, Set-DnsServerResourceRecordAging -NodeName. Microsoft notes it "stamps every record at a node" and says "Don't use it to age a single record." For an old record an admin created by hand, Microsoft's sanity-check advice: "you need to delete the record to clear the ownership and run the ipconfig /registerdns command to update it." For a record that should just go:
# Change. Dry-run first: remove one stale A record by name and address (Microsoft's example form; names are examples)
Remove-DnsServerResourceRecord -ZoneName 'contoso.com' -RRType 'A' -Name 'OLD-LT-022' -RecordData '10.20.30.41' -ComputerName DC02 -WhatIf
To keep a critical record from ever being scavenged, Microsoft's note: "No single cmdlet clears an existing record's timestamp." Its method is to remove the record and add it back without -AgeRecord, with its caution that this "changes the record's ownership and permissions and can affect later dynamic registration by the client."
DHCP (Step 6). Where DHCP registers records, make it clean up after expired leases. A dry run first:
# Change. Dry-run first: delete DNS records when the lease expires, for one scope (DynamicUpdates must be Always or OnClientRequest, per Microsoft)
Set-DhcpServerv4DnsSetting -ComputerName 'dhcp01.contoso.com' -ScopeId 10.20.30.0 -DeleteDnsRROnLeaseExpiry $true -WhatIf
If the DHCP server runs on a DC or several DHCP servers share clients, Microsoft's fix is a dedicated account for DNS updates (DHCP console: IPv4 > Properties > Advanced > Credentials), not the DnsUpdateProxy group alone: "When the DHCP server is a member of the DnsUpdateProxy group, it doesn't secure the DNS domain names it registers." Microsoft's dynamic update guide goes further and recommends letting clients register their own records: "the recommendation is not to use DHCP option 81 and instead let the client register its records." That's a design change; plan it with the network team (our view).
Intervals vs the lease (Steps 6, 8). Change the zone intervals or the scope lease, not both on the same day, and pick the direction from Step 6 on purpose. Keep refresh + no-refresh at least 24 hours in every case (Microsoft's Step 8 cases).
Then prove it. Microsoft's enable phase uses a test record: "create a new test record and enable it for scavenging. Then, map out the point in time when this record disappears."
# Change (one test record). Dry-run first; drop -WhatIf to create it. -AgeRecord gives it a timestamp
Add-DnsServerResourceRecordA -ZoneName 'contoso.com' -Name 'scavenge-test-01' -IPv4Address '192.0.2.250' -AgeRecord -ComputerName DC02 -WhatIf
# Read-only. Its timestamp, then the predicted deletion: timestamp + no-refresh + refresh, then the next pass after that (Step 5)
Get-DnsServerResourceRecord -ZoneName 'contoso.com' -Name 'scavenge-test-01' -ComputerName DC02 | Select-Object HostName, Timestamp
Microsoft's worked example: with 3-day intervals, a 3-day scavenging period, a last 2501/2502 at 6 AM on 1/1/2008, and a record stamped at noon that day, "you can predict that the record will be deleted at approximately 6 am on 1/10/2008." When your predicted time passes, confirm with the 2501 on DC02 and the 521 audit event naming scavenge-test-01, then check one Step 1 record the same way.
A manual pass is fine for a test once everything is eligible. Microsoft on Start-DnsServerScavenging: "If the DNS server cannot run scavenging, the cmdlet displays the reasons why the scavenge did not start." And from the troubleshooting article: "This will result in the instant deletion of records only if scavenging has been run automatically at least once on this server."
# Change (deletes eligible stale records). Dry-run first; -Verbose lists what it deletes (Microsoft's example)
Start-DnsServerScavenging -ComputerName DC02 -Verbose -WhatIf
When a change is justified
| Finding | Prefer | Avoid |
|---|---|---|
| Nobody scavenges | One server, without FSMO roles, 7-day period | Scavenging on every DC |
| Scavenge Servers names a dead DC |
dnscmd /zoneresetscavengeservers with the live server |
Waiting for more cycles |
| Old records are static | One record or one node stamped, or deleted after a check |
dnscmd /ageallrecords on the zone |
| DHCP owns stale records | Lease-expiry deletion, a dedicated DNS update account | DnsUpdateProxy alone in a secure-only zone |
| Live records being deleted | Interval 0 on the scavenging server, then longer intervals | Turning aging off and on repeatedly (it resets the clock) |
FAQ
Why is DNS scavenging not working?
Usually one of the three levels is missing. The server's scavenging interval is 0, aging is off for that zone, the zone only lets a different (often retired) server scavenge it, or the stale records have no timestamp. Event 2502 "no nodes were visited" on the server you configured points at the zone side first.
How long does DNS scavenging take to delete a stale record?
With defaults, a record becomes stale after 14 days without a refresh, and the next pass deletes it, so Microsoft says up to 21 days. A zone that just had aging turned on also waits one refresh interval before it can be scavenged at all.
Why are static DNS records not scavenged?
Their timestamp is 0, and scavenging only considers records with a nonzero timestamp. That's by design for servers and printers. To make one age, tick Delete this record when it becomes stale on that record. Avoid stamping the whole zone.
What are DNS events 2501 and 2502?
Both are logged by the scavenging server after a cycle. 2501 reports what it visited and scavenged and when the next cycle runs. 2502 means it completed a cycle with no nodes visited, and Microsoft's first listed cause is that no zones are configured for scavenging by that server.
What should the DNS refresh and no-refresh intervals be with DHCP?
Microsoft's pages don't agree on direction: the scavenging troubleshooting article says refresh + no-refresh should be at least the maximum DHCP lease, and the configuration article says equal to or less than the lease. Neither should be below 24 hours. Decide whether deleting a live record or keeping a reused address is the bigger risk in that subnet.
Related posts
- Active Directory Replication Error 1722 (a stale DC A record, and the replication health scavenging depends on)
- Windows Server DHCP Not Assigning IP Addresses (scopes, leases, and failover on the DHCP side of the same records)
- Netlogon Event ID 5719 (when a client finds the wrong DC through DNS)
- Windows Time Not Syncing With Domain Controller (staleness is measured against the DNS server's clock, so a wrong clock skews it; our reading)
Free checklist
Turning on scavenging on every DC with one-hour intervals before one test record was watched through a full cycle is a change nobody tested where the deletions happen. So is a Conditional Access policy enforced before anyone read the report-only results. The free Conditional Access pre-enforcement checklist keeps break-glass accounts, pilot groups, and report-only review on one page:
If you want the rest of the Intune runway written down for the team (enrollment hygiene, compliance phasing, break/fix cards and read-only PowerShell snapshots), the Intune & M365 Admin Starter Pack pairs with this triage: https://cashflow4375.gumroad.com/l/joonf?utm_source=devto&utm_medium=article&utm_campaign=aps_first_sale&utm_content=dns-scavenging-not-working
Admin Pack Studio; not affiliated with Microsoft. Steps 1-8 favor read-only checks: nltest /dclist, dnscmd /info, dnscmd /zoneinfo, Get-DnsServerScavenging, Get-DnsServerZone, Get-DnsServerZoneAging, Get-DnsServerResourceRecord, Get-WinEvent, Get-Acl, Get-ADObject, Get-DhcpServerv4DnsSetting, Get-DhcpServerv4Scope, Get-DhcpServerv4Lease, Get-DhcpServerDnsCredential, Resolve-DnsName, and repadmin. Export-DnsServerZone and output redirection write local files. Set-DnsServerScavenging, Set-DnsServerZoneAging, dnscmd /zoneresetscavengeservers, record timestamps, Remove-DnsServerResourceRecord, Set-DhcpServerv4DnsSetting, DHCP credentials, interval and lease changes, the test record, and Start-DnsServerScavenging are deliberate changes. Change one link at a time, prove it with one test record first, and check current Microsoft Learn for version-specific behavior.
Top comments (0)