Active Directory Directory foundations
Database maintenance and conflict objects
Transaction logs, white space, garbage collection, object counts and investigating CNF names without deleting the wrong object.
The DIT is only part of the storage picture
The database, transaction logs and checkpoint work together. edb.log is the active transaction log; numbered log files contain earlier generations; the checkpoint tracks recovery progress. File names, reserve files and format details vary by release. Do not delete logs to reclaim space on a live DC.
A committed change can be in the transaction log before its database pages reach disk. The checkpoint advances separately too. If logs are piling up, check storage, checkpoint progress and workload before putting it down to a busy DC.
Follow a write through the storage engine
ESE provides transactions and snapshot isolation inside the directory service’s process. The directory layers still enforce schema, object identity, access checks and replication semantics; a database file is not a supported alternative interface for changing a directory object. ESE’s architecture.
On a write, the change enters a transaction, the required log records become durable, and the operation completes. The modified database pages can be written later. After an interruption, ESE may need to replay the matching logs, starting from the checkpoint. The update can have committed successfully even though the database still needs that recovery work.
Check what the storage controller means when it acknowledges a write. If the data will disappear on power loss, a successful log flush can’t provide the durability AD expects. A large read cache won’t fix slow durable log writes either. Microsoft’s AD hardware guidance covers both.
Read the failure before choosing maintenance
| Observation | Investigation |
|---|---|
| DIT remains large after deletions | Retention, reusable internal space and whether physical compaction is actually needed |
| Transaction logs accumulate | Checkpoint progress, long-running work, disk free space and storage latency |
JET_errVersionStoreOutOfMemory |
Transaction/version-store pressure, workload and OS-specific sizing |
JET_errMissingLogFile (-528) |
Lost required log generation, restore consistency and storage history |
JET_errDatabaseDirtyShutdown (-550) |
Whether the database needs the matching transaction logs for recovery |
JET_errReadVerifyFailure (-1018) |
Checksum failure and the storage stack; this is not ordinary white space |
Preserve the exact JET code and the surrounding NTDS/ESENT events. Missing logs from one backup must not be replaced by similarly named files from another DC or another recovery point. Microsoft’s JET recovery reference maps the errors to recovery choices; replication error 8451 shows how a database fault can surface through replication.
Version store is a transaction resource
ESE retains versions needed by active transactions, including readers that must keep seeing a consistent view. Long-running work can keep versions alive while other activity creates more. Version-store exhaustion is therefore possible even when the DIT has free space and the server has otherwise usable memory.
Windows Server 2019 changed AD’s version-store sizing behavior. An old fixed-size recommendation can describe a different OS implementation, not a useful setting for the machine being investigated. Capture the server build, transaction workload, relevant events and performance during the symptom. Ryan Ries’s AD ESE version-store deep dive explains the change and diagnostic approach.
The long-running transaction might only be reading. Writers elsewhere can keep creating versions while that reader holds its view open. ESE’s transaction documentation explains why. Keep Directory Service/NTDS ISAM events such as 1519 and 623, including the instance, time window and full message. “Out of memory” is too broad to describe this failure. Microsoft’s AD version-store investigation.
If a reboot clears the symptom, you still need to find which transaction held the versions and whether it normally finishes. Bulk work may need to be reduced or rescheduled. Check the read buffer cache, process working set and version store separately; performance diagnosis helps put those measurements together.
Online free space does not shrink ntds.dit
Garbage collection processes objects eligible for final deletion and the database reuses internal free space. Online maintenance can improve that free space without reducing the file length. A large DIT after a mass deletion is not, by itself, evidence that garbage collection failed.
The historical default collection interval is 12 hours. Query the directory’s setting rather than modifying it to make a graph look better:
$dc = 'dc1.contoso.com'
$config = (Get-ADRootDSE -Server $dc).configurationNamingContext
$service = "CN=Directory Service,CN=Windows NT,CN=Services,$config"
Get-ADObject -Server $dc -Identity $service `
-Properties garbageCollPeriod,tombstoneLifetime,'msDS-DeletedObjectLifetime' |
Select-Object garbageCollPeriod,tombstoneLifetime,'msDS-DeletedObjectLifetime'
Unset attributes can mean that a default or fallback applies; they do not mean zero. Microsoft’s garbage collection reference explains the relationship between intervals and deletion retention.
Measure before considering offline compaction
Garbage Collection diagnostic logging can report database space, but enable it for a bounded collection and restore its previous value. Event IDs and reported fields vary with the operation and Windows release; read the event message to establish which maintenance operation and space measurement it describes.
Offline compaction creates a compacted database and requires an outage and a recovery plan. It is usually a poor first response to database growth. Decide whether reclaiming physical disk is worth the operation, or whether rebuilding one replica is simpler. Follow the current offline defragmentation procedure for the actual operating system. Hard repair is a separate recovery action, with very different support implications.
Compaction reorganizes storage. Soft recovery replays the required transaction logs. Hard repair can discard damaged data to make the database structurally readable. Whichever problem you’re dealing with, check the controller, virtual disk and caching layer. If the forest has healthy replicas, consider rebuilding the affected DC before attempting a lossy repair.
Database format is separate from the OS label
Windows Server 2025 introduces a 32 KB capable database format. Freshly created capable databases initially use 8 KB simulation for compatibility. An in-place upgraded DC can retain its older format. Enabling the forest feature requires the appropriate functional levels and capable databases throughout the forest; an OS inventory alone does not prove readiness.
Backup media retains its database format. Test the backup product’s restore path against the intended target before enabling a format change. Microsoft’s 32 KB feature guidance describes the format, simulation and eligibility distinctions.
Explain differences between replicas before compacting
Replicas can hold different naming contexts, GC partial replicas and DNS/application partitions. Their histories of deletion, growth and compaction can also leave different amounts of reusable internal space. Equal file length is not a replication invariant; unequal length does not by itself identify corruption.
Compare the data each DC hosts, live/deleted object counts, retention settings, maintenance and recent workload. A new replica may have less historical free space. That doesn’t mean the older replica lost data, and compaction won’t fix missing directory changes. Compare object identities and replication metadata for content problems, and use capacity planning to work out storage headroom.
Count objects with a defined scope
$domain = (Get-ADRootDSE -Server $dc).defaultNamingContext
[pscustomobject]@{
Server = $dc
Base = $domain
Users = (Get-ADUser -Server $dc -SearchBase $domain -Filter * |
Measure-Object).Count
Groups = (Get-ADGroup -Server $dc -SearchBase $domain -Filter * |
Measure-Object).Count
Computers = (Get-ADComputer -Server $dc -SearchBase $domain -Filter * |
Measure-Object).Count
}
These queries count visible live objects. They don’t include every internal record or deleted object. Save the server, base and collection time with the numbers, especially during a bulk import when replicas may temporarily disagree. Large enumerations also make work for the DC, so avoid running them repeatedly without a reason.
Find CNF objects
Replication resolves concurrent naming conflicts by assigning one object a conflict name containing a line feed and CNF: followed by a GUID. The LDAP escape for that line feed is \0a.
Get-ADObject -Server $dc -SearchBase $domain -SearchScope Subtree `
-LDAPFilter '(|(cn=*\0aCNF:*)(ou=*\0aCNF:*))' `
-Properties whenCreated,whenChanged,objectGUID |
Select-Object DistinguishedName,objectGUID,whenCreated,whenChanged
The domain base limits this search to one domain. Repeat against the required naming contexts if the question is wider.
A conflict name is a symptom, not a deletion instruction
Find which object the application or business actually needs, then check its GUID, links and consumers. Compare replication metadata to understand the competing creations or renames before changing either object. AD’s naming-conflict winner might not be the object you want to keep. Attribute version, timestamp and GUID-based tie-breaking take part in resolution; “always rename the oldest object” won’t reliably choose the right recovery.
For the underlying mechanisms, see replication internals. For accidentally removed objects, use object recovery.
Review LostAndFound as live data
LostAndFound is a special container for orphaned objects, not a second Deleted Objects container. An object there can still be a valid identity with permissions and application references. Its unexpected location can change inherited access and prevent an application scoped to the former OU from finding it. The schema definition identifies its orphan-container role and location-reconciliation trigger.
For a deliberate one-partition review:
$lostContainers = Get-ADObject -Server $dc -SearchBase $domain `
-SearchScope OneLevel -LDAPFilter '(objectClass=lostAndFound)'
foreach ($container in $lostContainers) {
Get-ADObject -Server $dc -SearchBase $container.DistinguishedName `
-SearchScope OneLevel -LDAPFilter '(objectClass=*)' `
-Properties whenCreated,whenChanged |
Select-Object ObjectGUID,ObjectClass,DistinguishedName,
whenCreated,whenChanged
}
Inspect the GUID, relationships, replication history and intended owner before moving or deleting anything. Neither whenChanged nor the container name establishes who caused the original parent/location problem. Repeat in the naming contexts relevant to the incident; a clean domain query does not inspect Configuration or an application partition. Preserve the intended destination’s delegation and application implications when planning a move.