Time is up for Exchange Server 2013, and you should be finalizing your migrations. If your migration is still ahead of you or nearing completion, then this post is for you.
We wanted to provide Microsoft’s best practices for preparing and planning your migration from Exchange 2013 to Exchange Server 2019. It’s important to note that because of the many different possible topologies and configurations for Exchange 2013, we can’t cover all migration scenarios, but the common steps are included here. That said, please plan your migration carefully and include all aspects of the environment, bearing in mind that some of the steps below may or may not apply to your situation (we will err on the side of over-communicating details).
Prepare
Here are a few references that will be useful to you throughout your migration:
- Exchange Server 2019 Architecture
- Exchange 2019 System Requirements
- Exchange Server Supportability Matrix
- Load Balancing in Exchange 2019
- Exchange 2019 Preferred Architecture
- Namespace Planning in Exchange 2019
Also, be sure to download the Exchange 2019 Sizing Calculator to correctly determine your Exchange 2019 hardware requirements.
Plan
In previous posts, we discussed the benefits of using the Exchange Deployment Assistant to plan and perform your migration. This post covers the manual steps required to perform a migration.
One of the first decisions to be made is how much availability do you need. Using the guidance in our High Availability and Site Resilience documentation will help you decide how available is available enough. When making that decision, consider all your failure domains, such as disk, network, server, virtualization loss (if applicable), datacenter failure, etc.
- Which of these failures will your design cover?
- Does your Exchange 2013 environment have any pain points that can be addressed by a new design with Exchange 2019?
Your plan should additionally include all associated costs, such as licensing, rack space, hardware, disk, network, bandwidth, backups, and if applicable, 3rd party apps.
Use an Active Directory deployment site
We recommend installing Exchange 2019 into an Active Directory deployment site. This prevents any internal domain-joined clients from looking up the SCP on Exchange 2019 servers.
Disable legacy TLS
We strongly recommend disabling TLS 1.0 and 1.1 in your organization as part of your migration. Be sure to read the guidance for this carefully since mistakes can cause big problems.
- Exchange Server TLS configuration best practices
- How to enable Transport Layer Security (TLS) 1.2 on clients
- Enable TLS 1.2 on servers
Use Office Online Server
We recommend using Office Online Server to enhance the attachment experience for Outlook and Outlook on the web users. Follow the steps in Install Office Online Server in an Exchange organization to utilize this in your environment.
Exchange 2019 client namespace planning
Our namespace guidance hasn’t changed much since Exchange 2013, so understanding your existing configuration will help you migrate to Exchange 2019. If your organization has Exchange namespaces, but they aren’t documented, you can fetch your organization’s namespaces using the following script:
The results show each unique namespace per protocol. If multiple results are returned in a single protocol, validate whether this configuration is required for a bound namespace model. We recommend that the internal URL and external URL be the same, and that split DNS is used for clients.
#Retrieve Result
$ClientAccess = Get-ClientAccessServer -ErrorAction:SilentlyContinue -WarningAction:SilentlyContinue
$MapiVdir = Get-MapiVirtualDirectory -ADPropertiesOnly
$EWSVdir = Get-WebservicesVirtualDirectory -ADPropertiesOnly
$EASVdir = Get-ActiveSyncVirtualDirectory -ADPropertiesOnly
$OWAVdir = Get-OwaVirtualDirectory -ADPropertiesOnly
$ECPVdir = Get-EcpVirtualDirectory -ADPropertiesOnly
$OABVdir = Get-OabVirtualDirectory -ADPropertiesOnly
$RPCVdir = Get-OutlookAnywhere -ADPropertiesOnly
#Find unique namespaces
[string[]]$AutodiscoverNS = $ClientAccess.AutoDiscoverServiceInternalUri.DNSSafeHost | Select-Object -Unique
[string[]]$MapiNS = $MapiVdir.InternalURL.DNSSafeHost | Select-Object -Unique
[string[]]$EWSNS = $EWSVdir.InternalURL.DNSSafeHost | Select-Object -Unique
[string[]]$EASNS = $EASVdir.InternalURL.DNSSafeHost | Select-Object -Unique
[string[]]$OWANS = $OWAVdir.InternalURL.DNSSafeHost | Select-Object -Unique
[string[]]$ECPNS = $ECPVdir.InternalURL.DNSSafeHost | Select-Object -Unique
[string[]]$OABNS = $OABVdir.InternalURL.DNSSafeHost | Select-Object -Unique
[string[]]$RPCNS = $RPCVdir.Internalhostname.Hostnamestring | Select-Object -Unique
[string[]]$RPCNS += $RPCVdir.Externalhostname.Hostnamestring | Select-Object -Unique
[string[]]$RPCNS = $RPCNS | Select-Object -Unique
[string[]]$OWADownloadNS = $OWAvdir.ExternalDownloadHostname | Select-Object -Unique
[string[]]$OWADownloadNS += $OWAvdir.InternalDownloadHostname | Select-Object -Unique
[string[]]$OWADownloadNS = $OWADownloadNS | Select-Object -Unique
#List individual protocols
Write-Host “AutoDiscover: $AutodiscoverNS“; Write-Host “Mapi: $MapiNS” ; Write-Host “EWS:” $EWSNS ; Write-Host “EAS: $EASNS” ; Write-Host “OWA: $OWANS” ; Write-Host “ECP: $ECPNS” ; Write-Host “OAB: $OABNS” ; Write-Host “RPC: $RPCNS” ; Write-Host “OWA Downloads: $OWADownloadNS”
Public folders
Supported Outlook clients for Exchange Server can access public folders. We recommend you migrate Exchange 2013 public folder mailboxes to Exchange 2019.
Kerberos with internal Outlook clients
Our guidance for this is based on whether your namespaces are shared between your Exchange 2013 and Exchanger 2019 servers. If they are, then you can use a single Alternative Service Account (ASA), which should ALWAYS be a computer account and not a user account.
Before making any changes, verify your existing configuration and then plan for your Exchange 2019 namespaces. You can also choose to create a new ASA with an updated naming convention, but that isn’t necessary for Kerberos to function.
In Exchange 2016 and later, use the Get-ClientAccessService cmdlet. You’ll see a warning if you use Get-ClientAccessServer, but it’s still functional.
Get-ClientAccessServer E15 -IncludeAlternateServiceAccountCredentialStatus | FL AlternateServiceAccountConfiguration
Identity: E15
AlternateServiceAccountConfiguration: Latest: <Not Set> Previous: <Not Set>
The Latest/Previous values will show <Not set> if this isn’t configured. It will show values for date/time when properly configured:
Get-ClientAccessServer E15 -IncludeAlternateServiceAccountCredentialStatus | FL AlternateServiceAccountConfiguration
Identity: E15
AlternateServiceAccountConfiguration: Latest: 3/9/2023 6:15:57 PM, contoso\EX2013-ASA$
Previous: <Not Set>
After installing Exchange 2019, you can run the RollAlternateServiceAccountPassword and target your Exchange 2019 server:
CD $ExScripts
.\RollAlternateServiceAccountPassword.ps1 -ToSpecificServer E19.contoso.com -CopyFrom E15.contoso.com
Now to verify this has been updated properly you can query the Exchange 2019 server:
Get-ClientAccessService E19 -IncludeAlternateServiceAccountCredentialStatus | FL AlternateServiceAccountConfiguration
Identity: E19
AlternateServiceAccountConfiguration: Latest: 3/9/2023 6:15:57 PM, contoso\EX2013-ASA$
Previous: <Not Set>
In our documentation for setting up Kerberos you’ll see that:
- The ASA must be a computer account to remain within support boundaries
- You can use one ASA for both Exchange 2013 and Exchange 2019
We don’t walk through the steps in this post, but we wanted to call attention to the above points. It should also be noted that there is a current limitation with this cross-version where you’ll want to make sure you’re looking up the ASA details from the local machine. Otherwise, you’ll get this error:
POP3 and IMAP clients
POP3 and IMAP4 services are set to Manual startup by default in Exchange 2019. If you have any clients that use these protocols, you’ll want to set these services to Automatic startup and keep them running. If you set these services to Automatic, you should disable POP and IMAP access at the mailbox level.
If you don’t need these services, we recommend leaving them set to Manual. Don’t set them to Disabled, or Managed Availability will believe the server has health issues.
Be sure to compare the values for ProtocolLogEnabled, InternalConnectionSettings, ExternalConnectionSettings, and x509CertificateName between servers for consistency in configuration.
Unified Messaging
This post does not cover Unified Messaging, because that feature has been removed from Exchange 2019. For detailed steps on migrating Unified Messaging to another solution, see Plan for Skype for Business Server and Exchange Server migration - Skype for Business Hybrid. Note, though, if your Exchange 2013 users have UM-enabled mailboxes, do not move them to Exchange 2019 before you move them to Skype for Business Server 2019, or they will have a voice messaging outage.
Deploy
When you are ready to deploy, create your own document or spreadsheet and add additional items that fit within your organization’s configuration needs.
Prepare Active Directory
Be sure to review Preparing AD and domains. The account you use must be a member of the Schema Admins and Enterprise Admins security groups to run /PrepareSchema, and a member of the Enterprise Admins security group to run /PrepareAD.
Examples:
Setup.exe /IAcceptExchangeServerLicenseTerms_DiagnosticDataON /PrepareSchema
Setup.exe /IAcceptExchangeServerLicenseTerms_DiagnosticDataON /PrepareAD
If you prepare Active Directory from a machine that is not an Exchange server, that machine must have the appropriate tools, including RSAT ADDS and .NET Framework 4.8.
If Active Directory preparation is not done before you install your first Exchange 2019 server, then Setup will try to perform these tasks during your first server installation. In that case, be sure to use an account that has the proper permissions.
If your forest consists of multiple domains, you will need to prepare each one. If you have only one domain, /PrepareAD will prepare it.
Examples:
Setup.exe /IAcceptExchangeServerLicenseTerms_DiagnosticDataON /PrepareDomain
Setup.exe /IAcceptExchangeServerLicenseTerms_DiagnosticDataON /PrepareAllDomains
Install Windows Server
This post does not cover installing Windows Server. Please follow the guidance in Exchange Server prerequisites, Exchange 2019 system requirements, Exchange 2019 requirements to plan your OS installation. After Windows Server is installed, and before you install Exchange Server, be sure to install the latest updates for Windows Server.
Pre-requisite script (Setup Assist)
Review the optional Setup Assist script and consider using it to prepare for installing Exchange 2019. This script is provided “as is” and is not supported, so be sure to test this script in your environment before using it in production.
.NET Framework
The pre-requisite script should ask you to install the appropriate version of the .NET Framework, but it’s worth calling out that the version installed should be a supported version and listed in the Exchange Server supportability matrix.
Install mailbox role
To demonstrate how to install the Mailbox role, we’re running Setup in unattended mode via an elevated command prompt, as documented in Use unattended mode in Exchange Setup. Always install the latest build of Exchange 2019, which you can determine here. Also see the section below about configuring anti-virus exclusions.
Setup.exe /IAcceptExchangeServerLicenseTerms_DiagnosticDataON /mode:Install /r:MB
There may be other Setup switches that are needed, so refer to the unattended mode document above for details.
Configure Exchange 2019 URL based on namespace
Based on the values identified during Exchange 2019 client namespace planning, you will want to update the values below based on your organization’s desired configuration. The sample below configures the URLs to be unique per protocol, using the root domain Contoso.com, and also configures the downloads domain for Outlook on the web to address this CVE.
#Stage variables for namespace modifiers
$InternetDomain = “contoso.com”
$EWSModifier = "EWS"
$ASModifier = "EAS"
$OWAModifier = "OWA"
$OWADownloadModifier = “Downloads”
$ECPModifier = "ECP"
$OABModifer = "OAB"
$MapiModifier = "MAPI"
$RPCModifier = "RPC"
#Stage variables containing the protocol’s full URL
$EwsUrl = "https://"+$EWSModifier+"."+$InternetDomain + "/EWS/Exchange.asmx"
$AsUrl = "https://"+$ASModifier+"."+$InternetDomain + "/Microsoft-Server-ActiveSync"
$OwaUrl = "https://"+$OWAModifier+"."+$InternetDomain + "/owa"
$OWADownloadsHostName = $OWADownloadModifier + "." + $InternetDomain
$EcpUrl = "https://"+$ECPModifier+"."+$InternetDomain + "/ecp"
$OabUrl = "https://"+$OABModifer+"."+$InternetDomain + "/OAB"
$MapiURL = "https://"+$MapiModifier+"."+$InternetDomain + "/mapi"
$RPCHostName = $RPCModifier + "." + $InternetDomain
#Update the Exchange Virtual Directories
Get-WebServicesVirtualDirectory -Server $Env:computername | Set-WebServicesVirtualDirectory -InternalURL $EwsUrl -MRSProxyEnabled $true -ExternalURL $EwsUrl -WarningAction:SilentlyContinue -Confirm:$false
Get-ActiveSyncVirtualDirectory -Server $Env:computername | Set-ActiveSyncVirtualDirectory -InternalURL $AsUrl -ExternalURL $AsUrl -WarningAction:SilentlyContinue -Confirm:$false
Get-OWAVirtualDirectory -Server $Env:computername | Set-OwaVirtualDirectory -InternalURL $OwaUrl -ExternalURL $OwaUrl -InternalDownloadHostName $OWADownloadsHostName -ExternalDownloadHostName $OWADownloadsHostName
-WarningAction:SilentlyContinue -Confirm:$false
Get-ECPVirtualDirectory -Server $Env:computername| Set-EcpVirtualDirectory -InternalURL $EcpUrl -ExternalURL $EcpUrl -WarningAction:SilentlyContinue -Confirm:$false
Get-OABVirtualDirectory -Server $Env:computername | Set-OabVirtualDirectory -InternalURL $OabUrl -ExternalURL $OabUrl -WarningAction:SilentlyContinue -Confirm:$false
Get-MapiVirtualDirectory -Server $Env:computername | Set-MapiVirtualDirectory -InternalURL $MapiURL -ExternalURL $MapiURL -WarningAction:SilentlyContinue -Confirm:$false
Get-OutlookAnywhere -Server $env:computername | Set-OutlookAnywhere -ExternalHostname $RPCHostName -SSLOffloading:$false -ExternalClientsRequireSsl:$True -InternalHostname $RPCHostName -InternalClientAuthenticationMethod:NTLM -InternalClientsRequireSsl:$true
-ExternalClientAuthenticationMethod:Basic -WarningAction:SilentlyContinue -Confirm:$false
Configure Autodiscover SCP for internal clients
If you don’t install Exchange in an Active Directory deployment site as we recommend, follow these steps instead.
The Get-ClientAccessService cmdlet is not available on Exchange 2013 and is used only for Exchange 2016 and later. In Exchange 2013 you need to run Get-ClientAccessServer.
When you install Exchange 2019, the server is ready to respond to incoming requests for internal clients. To prevent clients from accessing the newly installed server, we recommend that you point the SCP either to the Exchange 2013 Client Access server or set it to a NULL value by running the following command:
Set-ClientAccessService <ServerName> -AutodiscoverServiceInternalUri $NULL
It is easier to point the SCP to Exchange 2013, so you do not have to change it again. If the SCP is pointed to a server FQDN, we recommend you set the value to NULL temporarily; you can point this to Exchange 2019 later.
First, determine where the SCP is currently pointed:
Get-ClientAccessServer -Identity <Ex2013 CASName> | fl *auto*
Capture the AutoDiscoverServiceInternalUri value you get from the above command and point the Exchange 2019 SCP to NULL:
Set-ClientAccessService -Identity <Ex2019 ServerName> -AutoDiscoverServiceInternalURI $NULL
Configure the 2019 databases for default OAB
In Exchange 2013 and later, Offline Address Book (OAB) generation is managed by a mailbox assistant named OABGeneratorAssistant which runs under the Microsoft Exchange Mailbox Assistants service. OAB generation occurs in an arbitration mailbox.
These arbitration mailboxes need to be migrated to Exchange 2019, which moves OAB generation to Exchange 2019. If you customize your OAB distribution and you have multiple OAB generation mailboxes; you don’t to recreate the OAB. But be careful when assigning a new OAB to everyone as this action triggers a full download of the OAB for all clients, which could lead to network and performance issues. To check your configuration, run this command:
Get-OfflineAddressBook | FL Identity, GeneratingMailbox
Get-Mailbox –Arbitration | ?{$_.PersistedCapabilities -like “OrganizationCapabilityOABGen”} | FL Identity, Database, AdminDisplayVersion
Configure Exchange 2019 certificates
Depending on your plan, you may be using existing certificates or planning on creating new ones.
The Exchange Control Panel (ECP)-based certificate request was deprecated in Exchange 2019 CU12.
If you plan to use an existing 3rd party certificate for Exchange 2019, you must do the following:
1. Export the 3rd party certificate from Exchange 2013, using the instructions in Export a certificate from an Exchange server.
2. Import the 3rd party certificate into Exchange 2019, using the instructions at Import or install a certificate on an Exchange server. An example is shown below:
Import-ExchangeCertificate -FileData ([System.IO.File]::ReadAllBytes('<FilePathOrUNCPath>')) [-Password (ConvertTo-SecureString -String '<Password> ' -AsPlainText -Force)] [-PrivateKeyExportable <$true | $false>] [-Server <ServerIdentity>]
We recommend setting PrivateKeyExportable to $true when importing a certificate into Exchange Server. By enabling Private Key exportable, you can export the certificate with its private key.
Soon after importing the certificate, you must assign a service to it (especially SMTP). If you leave the certificate without assigning the SMTP service to it, Exchange may choose the unassigned certificate for SMTP communication and TLS communication will fail.
3. Assign services to the 3rd party certificate, using the instructions in Assign certificates to Exchange Server services.
- When you assign the SMTP service, Exchange Server prompts you to overwrite the existing default self-signed certificate set in the transport configuration (which you can check by running Get-TransportService <ServerName> | ft name, InternalTransportCertificateThumbprint). The Transport service uses a built-in self-signed certificate for internal communication, so it is not necessary to overwrite the self-signed certificate with the 3rd party certificate.
- Make sure the new certificate is bound to the IIS Default Web Site.
4. Follow step 2-3 to deploy the certificate on all other Exchange 2019 servers you add.
If you plan to create a new 3rd party certificate, you must do the following:
- Use the Exchange Management Shell (EMS) and follow the instructions in Create an Exchange Server certificate request for a certification authority. If you plan to use a certificate with multiple Subject Alternative Names (SANs) in place of a wildcard certificate, make you’re your certificate domains include all URLs set on your Exchange Server virtual directories and transport connectors.
- Complete pending request, using the instructions in Complete a pending Exchange Server certificate request.
- Follow steps 1-4 in the previous section to import the new certificate on your Exchange 2019 servers.
Create Database Availability Group(s)
Once you have familiarized yourself with the Exchange 2019 preferred architecture and the Exchange Server storage configuration options, you can create your DAGs following the guidance in Create a database availability group in Exchange Server.
When creating a DAG, you have the option of creating one with or without a cluster administrative access point. If you create a DAG with this access point, the cluster will not have a cluster name object (CNO) in Active Directory, and the cluster core resource group will not contain a network name resource or an IP address resource. We recommend this configuration because it means fewer resources are needed, making the DAG less complex. But note that in this configuration, you cannot use Failover Cluster Manager to manage the cluster. But since you should only manage DAGs using Exchange tools, you don’t need to use Failover Cluster Manager to manage a DAG.
Log truncation in Exchange 2019
Be aware of changes in behavior for log truncation in Exchange 2019. One of the reasons for these changes is due to how Workload Management (WLM) prioritizes threads on a server and balances this prioritization across our Exchange services (as it’s intended). This results in a higher threshold for required logs before truncation will occur, and this threshold will be different as active users are moved to these databases.
Configure anti-virus exclusions
For years we have been saying how running antivirus (AV) software on your Exchange Servers can enhance the security and health of your Exchange organization. We’ve also said that if you are deploying file-level scanners on Exchange servers, make sure that the appropriate exclusions, such as directory exclusions, process exclusions, and file name extension exclusions, are in place for both scheduled and real-time scanning.
When configuring antivirus software for Exchange Server, be sure to exclude all the items described here and here. If you use Windows Defender, you can use a script we built to make this easier.
Configure connectors
The next step is to configure Connectors.
Receive connectors
Exchange 2019 has the same number of default receive connectors as Exchange 2013. No modifications are needed if your default receive connectors were not customized in Exchange 2013.
SMTP relay receive connector
Be sure to review any SMTP relay receive connector(s) on Exchange 2013 and configure an SMTP relay receive connector on Exchange 2019 with the same configuration. This is required for any on-premises applications that need to relay emails through Exchange 2019. For more information, see Allow anonymous relay on Exchange servers.
Send connectors
Replace any Exchange 2013 servers with Exchange 2019 server in the ‘SourceTransportServers’ for all Send connectors.
If you have an Exchange hybrid environment, make sure that TLSCertificateName is configured correctly on your Connectors in both Exchange Server and Exchange Online. The Hybrid Configuration Wizard (HCW) is responsible for making the required changes on hybrid connectors.
Edge transport server
You can use the following resources to deploy Exchange 2019 Edge Transport in your environment:
- Install Exchange Edge Transport servers using the Setup wizard
- Import 3rd party certificate and assign SMTP service. See Import or install a certificate on an Exchange server.
- Edge subscriptions are mandatory for hybrid mail flow. See Edge Subscriptions. In a hybrid environment, you also need to run the HCW (Hybrid Configuration Wizard).
- If you add a new Mailbox server to a subscribed Active Directory site, and you it to participate in EdgeSync synchronization, you need to resubscribe your Edge Transport servers. See Procedures for Edge Subscriptions.
Run the Exchange Server Health Checker
Health Checker identifies potential critical issues. We strongly recommend running it and thoroughly review its findings. You should implement all recommendations to avoid potential outages or performance issues. Health Checker isn’t just for migration. It’s for ongoing management of Exchange Server. Keep it handy, as it is one of your most value admin tools.
Migrate
Now that we have completed the deployment of Exchange 2019, the next step is to migrate.
Create a test mailbox on 2019
We recommend that you create a test mailbox (non-admin) and verify connectivity using the protocols your organization uses. Consider any workflows you have, such as connecting to an archive mailbox, using public folders, and delegation scenarios. Test Outlook, Free/Busy, Outlook on the web, ActiveSync, out of office, and any custom or third-party applications.
Test connection for Exchange 2013 mailbox
Test and verify that Exchange 2013 mailboxes can connect through Exchange 2019 by creating a HOSTS file entry on a client machine with the IP address of an Exchange 2019 server using the load balanced namespace. Check the Connection Status window to verify that the proxy server column is populated, and the connection is HTTP or HTTPS.
The Hosts file is in C:\Windows\System32\Drivers\etc directory. It is protected and can only be edited through an elevated text editor, such as Notepad. An example host entry that redirects your workstation traffic from your Load Balancer (mail.contoso.com) to a single server endpoint (192.168.1.5) would look like this:
192.168.1.5 mail.contoso.com
Point the SCP to Exchange 2019
If Exchange 2019 was installed into an existing site and the SCP was temporarily moved to Exchange 2013 or set to NULL, it needs to be updated. Depending on your configuration, you should point the SCP to either the internal FQDN of the Exchange 2019 server or to your load balanced namespace.
Move arbitration mailboxes
Next, move the system and arbitration mailboxes from Exchange 2013 to Exchange 2019 prior to other mailboxes. This is required for many things to work properly, including the Exchange Admin Center (EAC). To see which system mailboxes are on Exchange 2013, run the following commands:
Set-ADServerSettings -ViewEntireForest $True
Get-Mailbox -Arbitration | FT Name, Database -AutoSize
To migrate arbitration mailboxes from Exchange 2013 to Exchange 2019, run the following commands:
Set-ADServerSettings -ViewEntireForest $True
Get-Mailbox -Arbitration | New-MoveRequest -TargetDatabase <Ex2019DatabaseName>
Namespace changes
Once you have verified client connectivity, change your DNS records from Exchange 2013 to Exchange 2019, modify any load balanced pools, update firewall rules, NAT assignments, etc.
Hybrid configuration
After all dependencies (virtual directory URLs, Autodiscover, DNS, exchange certificates, etc.) are in place, you are ready to run the HCW.
There are two options for configuring a hybrid organization:
The HCW is best for complex hybrid deployments, especially those that require multi-forest, sharing policies, etc.
The Modern Hybrid Agent (MHA) is best for simpler deployments that only require Free/Busy and mailbox migration to Exchange Online. MHA does not support things like Hybrid Modern Authentication for on-premises, multi-forest exchange environment, cross-premises teams calendaring, and cross-premises message tracking. MHA is designed for organizations that do not already have a hybrid configuration in place.
Run the HCW and input the servers that will be handling hybrid functions.
Move administrator mailboxes
Use either EAC or the PowerShell to move administrator mailboxes to Exchange 2019.
PowerShell Example:
New-MoveRequest-Identity user@domain.com -TargetDatabase <Ex2019DatabaseName>
Move mailboxes
See Managing mailbox moves for more information about migrating mailboxes. When moving mailboxes, note that increased log generation will occur on both the source and target databases. Plan your moves to coincide with your backups to help manage free space for your databases. Otherwise, you risk databases dismounting during or after mailbox move operations.
Migrate public folders
Our guidance for migrating public folders is in Migrate public folders from Exchange 2013 to Exchange 2016 or Exchange 2019.
Remove legacy Exchange versions
After you have finished deploying and configuring Exchange 2019, and moving all mailboxes and public folders, you can remove Exchange 2013. For more information, see Decommissioning Exchange Server 2013.
We want to thank the following people for helping with this post: Nino Bilic, Rob Whaley, Bhalchandra Atre, Paul Newell, Mike Brown, and Scott Schnoll.
Jason Lockridge, Shashank Agarwal, Jason Burnside, David Loegering and Josh Hagen (Exchange)
You Had Me at EHLO.