Checklist
DAG patching with maintenance mode checklist
Based on the article: Patching a DAG without downtime: Exchange Server maintenance mode step by step · 5 min read
Patching a member of a database availability group (DAG) is routine, but one skipped step is all it takes to strand mail in the queue of a rebooting server, leave a node able to grab the Primary Active Manager role, or end up with databases that never move back. In this post I'll walk through Microsoft's supported maintenance-mode sequence for Exchange Server SE, explain what each command actually does, and show what "good" looks like before and after you patch.
Before you start
Start with a quick health check:
- An elevated Exchange Management Shell on the server you're patching (EX01 in the examples). The DAG scripts can also run remotely, but the machine running them needs the Failover Cluster Management tools (RSAT-Clustering).
- A healthy passive copy of every database that's active on EX01, and another Mailbox server (EX02.contoso.com here) to receive redirected mail.
- The CU or SU that matches your current build, downloaded in advance and checked against Microsoft's Exchange build numbers page.
- A note of EX01's current activation policy, because the stop script resets it to
Unrestricted.
Get-MailboxDatabase | Get-MailboxDatabaseCopyStatus |
Format-Table Name,Status,CopyQueueLength,ReplayQueueLength -AutoSize
Test-ReplicationHealth -Identity EX01
Get-MailboxServer EX01 | Format-List DatabaseCopyAutoActivationPolicyChecklist
- 1
Drain transport
powershellSet-ServerComponentState EX01 -Component HubTransport -State Draining -Requester Maintenance Restart-Service MSExchangeTransportThe restart makes the Transport service pick up the draining state straight away. Microsoft's procedure restarts only
MSExchangeTransport; Front End Transport is a stateless proxy and doesn't queue mail. - 2
Move databases and pause the cluster node
powershellcd $ExScripts .\StartDagServerMaintenance.ps1 -ServerName EX01 -MoveComment Maintenance -PauseClusterNodeThe script can run for several minutes without printing anything, so be patient. Both DAG scripts accept
-WhatIfif you want a dry run first. - 3
Redirect queued messages
powershellRedirect-Message -Server EX01 -Target EX02.contoso.com -Confirm:$false Get-Queue -Server EX01 | Where-Object { $_.MessageCount -gt 0 }The target must be the FQDN of another Mailbox server that isn't in maintenance. Repeat the
Get-Queuecheck until it returns nothing, or only Shadow Redundancy queues. - 4
Take the server offline
powershellSet-ServerComponentState EX01 -Component ServerWideOffline -State Inactive -Requester MaintenanceIf your load balancer probes each protocol's
healthcheck.htmpage, those probes now fail and EX01 drops out of the pool. If it only checks that a port is open, disable EX01 in the load balancer yourself. - 5
Confirm, then patch
powershellGet-ServerComponentState EX01 | Format-Table Component,State -AutoSize Get-MailboxServer EX01 | Format-List DatabaseCopyAutoActivationPolicy Get-ClusterNode EX01 | Format-List Name,State Get-MailboxDatabaseCopyStatus -Server EX01 | Where-Object { $_.Status -eq "Mounted" }You're ready when only
MonitoringandRecoveryActionsEnabledare still active, the policy showsBlocked, the node isPausedand the last command returns nothing. - 6
Bring the server back
powershellSet-ServerComponentState EX01 -Component ServerWideOffline -State Active -Requester Maintenance cd $ExScripts .\StopDagServerMaintenance.ps1 -ServerName EX01 Set-ServerComponentState EX01 -Component HubTransport -State Active -Requester Maintenance Restart-Service MSExchangeTransportThe stop script resumes the cluster node, sets the activation policy to
Unrestrictedand resumes the server's database copies. If your original policy was different, put it back, for exampleSet-MailboxServer EX01 -DatabaseCopyAutoActivationPolicy IntrasiteOnly. - 7
Rebalance, then move to the next server
Since Exchange 2016 CU2, the DAG's
PreferenceMoveFrequencysetting rebalances active databases automatically. To rebalance immediately instead:powershellcd $ExScripts .\RedistributeActiveDatabases.ps1 -DagName DAG01 -BalanceDbsByActivationPreference
Verify
Get-ServerComponentState EX01 | Where-Object { $_.State -ne "Active" }
Get-ClusterNode | Format-Table Name,State
Get-MailboxDatabaseCopyStatus -Server EX01 |
Format-Table Name,Status,CopyQueueLength,ReplayQueueLength -AutoSize
Test-ServiceHealth EX01
Get-Command ExSetup.exe | ForEach-Object { $_.FileVersionInfo.FileVersion }Good looks like this:
- Only
ForwardSyncDaemonandProvisioningRpsare listed; both are inactive by default on-premises. - Every cluster node is
Up. - EX01's copies are
HealthyorMounted, with low queue lengths. RequiredServicesRunningisTruefor every role listed.- The ExSetup version matches the build Microsoft lists for the update you installed, and a test message flows through EX01.
Tips & gotchas
- Components still inactive after a failed update? Setup records its own requester. Microsoft's fix is to set
ServerWideOffline,MonitoringandRecoveryActionsEnabledback toActivewith-Requester Functional. TheLocalStatesandRemoteStatesproperties ofGet-ServerComponentStateshow which requester set each state. - Two-member DAGs. While one member is paused or rebooting, the other carries every database with no redundancy, and quorum depends on the file share witness. Check that the witness server is reachable before you reboot.
- Prefer the scripts to hand-typed sequences. They handle the PAM move and the activation block for you, and the start script rolls itself back if something fails.
- Review mitigations after patching. An update can make an Emergency Mitigation service mitigation unnecessary; see Exchange Emergency Mitigation service and AMSI for the checks.