After patching, a failover or a simple reboot, you often find most databases in a database availability group (DAG) active on one or two members while the others sit idle. In this post I'll explain how activation preference really works, why Exchange Server SE and Exchange 2019 normally move databases back on their own (and what stops them), and how to rebalance on demand with RedistributeActiveDatabases.ps1 or Move-ActiveMailboxDatabase.
How it works#
Every database copy has an ActivationPreference number: 1 is the most preferred copy, and each copy of a database gets a different number. The value is used in two places:
- Failovers. When a server or database fails, Active Manager's best copy and server selection picks the healthiest, most up-to-date copy. Health and the copy and replay queues come first; preference only breaks ties. After an unplanned failover a database can land on its third choice and stay there.
- Automatic rebalancing. Since Exchange 2016 CU2 (and therefore in Exchange 2019 and SE), the DAG property
PreferenceMoveFrequencytells the Microsoft Exchange Replication service how often to perform a lossless switchover back to the copy with preference 1, provided that server and copy are healthy. The default is one hour.
So "databases on the wrong server" almost always means one of three things: the preference numbers are unbalanced, automatic rebalancing has been switched off, or something blocks activation on the preferred member. Run the commands below in the Exchange Management Shell with Organization Management rights.
Step-by-step: put databases back where they belong#
1. See where everything is active#
Get-MailboxDatabase | Sort-Object Name | Format-Table Name, Server, ActivationPreference -AutoSize
Get-DatabaseAvailabilityGroup DAG01 | Format-List Name, PreferenceMoveFrequencyServer is the member currently hosting the active copy, and ActivationPreference lists every copy, for example {[EX02, 1], [EX01, 2]}. A database showing EX01 with that list belongs on EX02. PreferenceMoveFrequency should read 01:00:00 unless someone changed it.
For a per-server view, run the script that ships with Exchange without a balancing switch, so it only reports:
cd $exscripts
.\RedistributeActiveDatabases.ps1 -DagName DAG01 -ShowDatabaseDistributionByServer | Format-TableThe PreferenceCountList column counts copies per preference: {2, 2} means two copies at preference 1 and two at preference 2. If one member shows {4, 0} and its partner {0, 4}, no amount of rebalancing will share the load. Fix the preferences first.
2. Correct the preferences#
Set-MailboxDatabaseCopy -Identity "DB03\EX02" -ActivationPreference 1Aim for every member to be preference 1 for an equal share of databases, and give lagged copies the highest number. With automatic rebalancing on, a new preference 1 can trigger a switchover within the next interval, so change preferences in a quiet period.
3. Clear whatever blocks activation#
Both the hourly rebalancing and the script skip a target that isn't healthy or isn't allowed to host active copies. Check the preferred member:
Get-MailboxServer EX02 | Format-List DatabaseCopyAutoActivationPolicy, DatabaseCopyActivationDisabledAndMoveNow, MaximumActiveDatabases
Get-ServerComponentState EX02 | Where-Object State -ne 'Active'
Get-MailboxDatabaseCopyStatus -Server EX02 | Format-Table Name, Status, ActivationSuspended, CopyQueueLength, ReplayQueueLength, ContentIndexState -AutoSize| What you see | Meaning | Fix |
|---|---|---|
DatabaseCopyAutoActivationPolicy : Blocked | Exchange won't activate copies on this server by itself (often left over from maintenance) | Set-MailboxServer EX02 -DatabaseCopyAutoActivationPolicy Unrestricted |
DatabaseCopyActivationDisabledAndMoveNow : True | Exchange keeps moving active databases off this server | Set-MailboxServer EX02 -DatabaseCopyActivationDisabledAndMoveNow $false |
ServerWideOffline or HighAvailability listed as Inactive | Maintenance mode was never fully ended | Set the component back to Active with the requester that disabled it, for example Set-ServerComponentState EX02 -Component ServerWideOffline -State Active -Requester Maintenance |
ActivationSuspended : True | Copy-level block set with Suspend-MailboxDatabaseCopy -ActivationOnly | Resume-MailboxDatabaseCopy DB03\EX02, but leave lagged copies blocked |
Active count equals MaximumActiveDatabases | The server refuses more active copies | Raise the value with Set-MailboxServer |
Copy not Healthy, high queues or a failed content index | Not a valid switchover target | Repair or reseed the copy before rebalancing |
Most of these come from an incomplete exit from maintenance mode; the full sequence is in Patching a DAG without downtime.
4. Rebalance now#
cd $exscripts
.\RedistributeActiveDatabases.ps1 -DagName DAG01 -BalanceDbsByActivationPreference -ShowFinalDatabaseDistributionThe script works database by database and asks before each switchover (answer A for Yes to All, or add -Confirm:$false). Healthy output looks like this:
Considering move of 'DB03' from 'EX01' (AP = 2) to 'EX02' (AP = 1)...
Database 'DB03' successfully moved from 'EX01' to 'EX02'.In a DAG stretched across two sites, use -BalanceDbsBySiteAndActivationPreference instead; it also tries to keep active databases even within each Active Directory site. For a single database, a manual switchover is quicker:
Move-ActiveMailboxDatabase DB03 -ActivateOnServer EX02 -Confirm:$falseIf it fails, the error names the check that blocked it: copy or replay queue, content index, maximum active databases and so on. The cmdlet has skip switches such as -SkipClientExperienceChecks, but keep them for emergencies. The checks exist to stop you activating a copy that is behind or has a broken search index.
5. Decide how automatic rebalancing should run#
The hourly default suits most DAGs and removes the need for scheduled rebalancing scripts. If your change process forbids unplanned switchovers during business hours, lengthen the interval, or turn it off and rebalance in a maintenance window instead:
# Check once a day instead of every hour
Set-DatabaseAvailabilityGroup DAG01 -PreferenceMoveFrequency 1.00:00:00
# Turn automatic rebalancing off
Set-DatabaseAvailabilityGroup DAG01 -PreferenceMoveFrequency ([System.Threading.Timeout]::InfiniteTimeSpan)Verify#
Get-MailboxDatabaseCopyStatus * | Where-Object Status -eq 'Mounted' |
Group-Object MailboxServer | Format-Table Name, Count -AutoSize
Get-MailboxDatabase | Sort-Object Name | Format-Table Name, Server, ActivationPreference -AutoSizeGood looks like this: each database's Server matches its preference-1 copy, the mounted count per member is roughly even, and every passive copy reports Healthy with queues close to zero. Check again after the next interval to make sure nothing drifts back.
Tips & gotchas#
- Don't rebalance onto a struggling server. Fix replication, disk or search problems first, or databases will bounce away again at the next failover. Running the Exchange Server Health Checker beforehand is cheap insurance.
- Lagged copies belong at the highest preference number with activation suspended, so neither a failover nor rebalancing picks them by accident.
- Multi-site DAGs:
DatabaseCopyAutoActivationPolicy IntrasiteOnlyon disaster-recovery members stops Exchange automatically activating copies there from the other site. - Preference is not a pin. A database can still fail over to any healthy copy; preference decides where it should return, not where it must stay.
- Read the script's final table.
-ShowFinalDatabaseDistributionshows active and passive counts per server after the run, which is the quickest proof the rebalance worked.

