A passive database copy is only as useful as it is current. When CopyQueueLength or ReplayQueueLength climbs into the hundreds or thousands, a failover can lose data, take longer, or not happen automatically at all. In this post I'll explain what each queue measures, how to tell a network problem from a storage problem or a lagged copy that's simply doing its job, and how to watch the queues drain on Exchange Server SE and Exchange 2019.
Errors this guide fixes
DBLogCopyKeepingUp *FAILED*Test-ReplicationHealthDBLogReplayKeepingUp *FAILED*Test-ReplicationHealthDBDisconnected *FAILED*Test-ReplicationHealthDisconnectedAndHealthyGet-MailboxDatabaseCopyStatusDisconnectedAndResynchronizingGet-MailboxDatabaseCopyStatus
Symptoms#
Get-MailboxDatabaseCopyStatus * | Sort-Object CopyQueueLength -Descending |
Format-Table Name,Status,CopyQueueLength,ReplayQueueLength -AutoSizeName Status CopyQueueLength ReplayQueueLength
---- ------ --------------- -----------------
DB03\EX03 DisconnectedAndHealthy 2310 0
DB01\EX02 Healthy 2 846Test-ReplicationHealth across the DAG flags the same copies:
Get-DatabaseAvailabilityGroup DAG01 | Select-Object -ExpandProperty Servers |
Test-ReplicationHealth | Where-Object { $_.Result.Value -ne "Passed" }Server Check Result Error
------ ----- ------ -----
EX03 DBDisconnected *FAILED* Failures:...
EX03 DBLogCopyKeepingUp *FAILED* Failures:...
EX02 DBLogReplayKeepingUp *FAILED* Failures:...Alongside these you may see:
- Copies in
DisconnectedAndHealthyorDisconnectedAndResynchronizing, states Microsoft notes can appear during DAG network failures between the source and target copies. - The log volume on the active server filling up even though backups run, because logs a passive copy still needs can't be truncated.
- A database that doesn't mount automatically after a failover, or takes a long time to mount.
Why it happens#
What the two queues measure#
Continuous replication is a pipeline. The active copy writes transaction logs; the Microsoft Exchange Replication service on each passive server copies them and inspects them for corruption; then it replays them into the passive database.
- CopyQueueLength counts logs the active copy has generated that this passive copy hasn't yet copied and inspected. It measures data at risk: if the active copy were lost now, those logs would be missing on the passive.
- ReplayQueueLength counts logs that are safely on the passive server but not yet written into its database. Nothing is lost, but a failover has to replay them before the database can mount.
The copy queue decides what happens in an unplanned failover. The AutoDatabaseMountDial setting on each Mailbox server sets how many missing logs Exchange accepts before mounting automatically: Lossless (none), GoodAvailability (up to 6) or BestAvailability (up to 12). Check yours with Get-MailboxServer | Format-Table Name,AutoDatabaseMountDial.
Reading the pattern#
| Pattern | Likely cause |
|---|---|
High copy queue, status DisconnectedAndHealthy | Network failure between source and target: firewall, routing, NIC or WAN link |
| High copy queue on every copy across one site link | Not enough bandwidth, or too much latency, for the log generation rate |
High copy queue on a Suspended or Failed copy | Nothing is being copied; resume or repair the copy |
| High replay queue on all copies on one server | Slow or overloaded storage on that passive server, or antivirus scanning database and log folders |
| High replay queue on one copy that never drains | A lagged copy working as designed |
| Both queues spike, then drain | Bursts of log generation from mailbox moves, migrations, imports or bulk deletes |
How to fix it#
1. Rule out lagged copies#
Get-MailboxDatabase DB01 | Format-List Name,ReplayLagTimes
Get-MailboxDatabaseCopyStatus -Identity "DB01\EX04" | Format-List Name,ReplayQueueLength,ReplayLagStatusA copy with a replay lag (set with Set-MailboxDatabaseCopy -ReplayLagTime, up to 14 days) holds logs back on purpose, so a large replay queue there is normal. Leave lagged copies out of your replay-queue alerts.
2. Copy queue: check the replication path#
Get-MailboxDatabaseCopyStatus -Server EX03 -ConnectionStatus |
Format-List Name,Status,CopyQueueLength,IncomingLogCopyingNetwork
Get-DatabaseAvailabilityGroupNetwork | Format-Table Name,Subnets,ReplicationEnabled,MapiAccessEnabled -AutoSize
Get-DatabaseAvailabilityGroup DAG01 | Format-List ReplicationPort,NetworkCompression,NetworkEncryption
Test-NetConnection EX01 -Port 64327Check that:
- The copy uses the network you expect (
IncomingLogCopyingNetwork), and that network is up on every member. - The replication port (64327 by default) is open in both directions between DAG members, including through any firewall or WAN optimiser between sites.
- Compression is still on between subnets. The default,
InterSubnetOnly, compresses replication traffic that crosses subnets. - The link can carry your peak log generation. Each log file is 1 MB, so a database writing 30 logs a minute needs about 4 Mbit/s for each remote copy, before compression and protocol overhead.
If the network is fine but one copy stays stuck, restart the Microsoft Exchange Replication service (MSExchangeRepl) on the passive server, ideally after moving any active databases off it. A suspended copy collects copy queue by definition; resume it with Resume-MailboxDatabaseCopy once its problem is fixed.
3. Replay queue: check the passive server's storage#
$counters = "\MSExchange Replication(*)\ReplayQueueLength",
"\LogicalDisk(*)\Avg. Disk sec/Read",
"\LogicalDisk(*)\Avg. Disk sec/Write"
Get-Counter -ComputerName EX03 -Counter $counters -SampleInterval 5 -MaxSamples 12Replay is write-heavy work on the passive database volume. If latency on the database or log volumes stays high while the replay queue grows, look at the storage: failed disks or a degraded array, a controller cache problem, a busy shared storage pool or virtualization host, or antivirus scanning the database folders. Also check what else the server is doing: a reseed, a backup reading from the passive copy, or (on Exchange 2016) a content index crawl all compete for the same disks.
4. Bursts from migrations and bulk changes#
Mailbox moves, PST imports, retention clean-ups and large deletions generate logs far faster than normal mail flow. Queues that rise during these jobs and drain afterwards are expected. If they don't drain, run fewer moves in parallel and schedule them outside business hours.
Verify the fix#
Test-ReplicationHealth -Identity EX03 |
Where-Object { $_.Check -like "DBLog*" -or $_.Check -eq "DBDisconnected" }
Get-MailboxDatabaseCopyStatus -Server EX03 |
Format-Table Name,Status,CopyQueueLength,ReplayQueueLength -AutoSizeGood looks like DBLogCopyKeepingUp, DBLogReplayKeepingUp and DBDisconnected returning Passed, copies back to Healthy, and both queues in low single digits for every copy that isn't lagged. To prove the fix holds over time, sample the whole DAG with Microsoft's script from the Exchange Scripts folder:
cd $ExScripts
.\CollectReplicationMetrics.ps1 -DagName DAG01 -Duration "01:00:00" -Frequency "00:01:00" -ReportPath C:\ReplMetricsIt collects the replication performance counters from every member and writes a summary (HaReplPerfReport.*.csv) with average copy and replay queue lengths and how long copies spent failed, suspended or outside their failover criteria. Run it once during a normal business hour and once during your busiest window.
Prevent it next time#
- Alert on trends, not single samples: a copy queue that stays above a few dozen logs for several minutes deserves a look.
- Size WAN links and storage for peak log generation, migration weekends included, not for average mail flow.
- Keep antivirus exclusions for database and log folders in place.
- Patch members one at a time with maintenance mode, so replication never runs without spare capacity: Patching a DAG without downtime.
- If a copy ends up
FailedAndSuspendedrather than just behind, follow Database copy FailedAndSuspended in a DAG. If members keep dropping out of the cluster, see DAG cluster problems and Event ID 1135.

