A load balancer in front of Exchange Server only helps if it knows when a protocol on one server is unhealthy, and if it leaves Exchange's authentication intact. In this post I'll set up the parts that matter on any F5 BIG-IP, Kemp LoadMaster or NetScaler: per-protocol health checks, SSL handling that survives Extended Protection, persistence, SMTP and Kerberos, then match the symptoms of a VIP that gets them wrong.
Errors this guide fixes
HTTP Error 503. The service is unavailable.Browser (OWA / ECP)The connection to Microsoft Exchange is unavailable. Outlook must be online or connected to complete this action.Outlook+1 more guideThe Kerberos client received a KRB_AP_ERR_MODIFIED error from the serverSystem log (Event ID 4)+1 more guide550 5.7.54 SMTP; Unable to relay recipient in non-accepted domainSMTP client / app relaying via the VIP+7 more guides
How it works#
Since Exchange 2016 every native client uses HTTP(S), and whichever Mailbox server receives a request proxies it to the server hosting the active mailbox copy. Microsoft's load-balancing guidance therefore states that session affinity is no longer required. The sign-in cookie is encrypted with the Client Access services certificate, so any server holding the same certificate can read it. Windows NLB can't run alongside the clustering that DAG members use, which is why appliances or virtual load balancers are the norm.
| Layer 4 | Layer 7 | |
|---|---|---|
| Sees | IP address, protocol, port | The HTTP path (/owa, /mapi, /Microsoft-Server-ActiveSync) |
| Health | One probe per namespace: if it fails, the server leaves the pool for every protocol (unless each protocol gets its own namespace) | One probe per virtual directory: only the failed protocol moves |
| TLS | Passed through to Exchange | Terminated on the load balancer |
Microsoft recommends a single namespace, no affinity and layer 7 for Exchange 2016 and 2019 (the same applies to Exchange Server SE). The link to Exchange's own monitoring is healthcheck.htm: when Managed Availability's offline responder takes a protocol, or the whole server, out of service, https://<server>/<vdir>/healthcheck.htm stops answering 200. A probe on / or on TCP 443 only proves IIS is up. The same mechanism drains a server in maintenance mode.
Step-by-step#
1. Namespace and certificate#
Publish one namespace (for example mail.contoso.com) plus autodiscover.contoso.com on the VIP, and set every virtual directory URL to it. Install the same certificate on every server behind the VIP and, if the load balancer terminates TLS, on the load balancer.
2. One monitor per protocol#
Create an HTTPS monitor for each pool: /owa/healthcheck.htm, /ecp/healthcheck.htm, /ews/healthcheck.htm, /mapi/healthcheck.htm, /Microsoft-Server-ActiveSync/healthcheck.htm, /oab/healthcheck.htm, /autodiscover/healthcheck.htm and /rpc/healthcheck.htm if Outlook Anywhere is still used. Mark a member up only on HTTP 200. With layer 4 and one namespace, Microsoft suggests probing your most-used virtual directory.
On F5 BIG-IP, don't use the default http/https monitors: F5 documents that without a Receive String they accept any response. Build a custom HTTPS monitor whose Send String is a complete HTTP/1.1 request (HTTP/1.1 requires a Host header):
Send String: GET /owa/healthcheck.htm HTTP/1.1\r\nHost: mail.contoso.com\r\nConnection: Close\r\n\r\n
Receive String: 200 OKOn Kemp LoadMaster and NetScaler, configure the equivalent HTTPS check per service: the health-check URL path, your namespace as host, success only on 200.
3. Bridge SSL, don't offload it#
Extended Protection is on by default from Exchange 2019 CU14, and Microsoft requires SSL offloading for Outlook Anywhere to be disabled. Terminating TLS on the load balancer and sending plain HTTP to Exchange breaks Windows authentication under Extended Protection; re-encrypt to Exchange (SSL bridging) with the same certificate on the load balancer and the servers, which is Microsoft's condition for supporting Extended Protection with SSL bridging. On LoadMaster that's SSL Acceleration › Reencrypt on the Exchange virtual service, as the Progress Community article describes. Layer 4 passthrough is also fine, because TLS ends on Exchange.
Get-OutlookAnywhere | Format-Table Server,SSLOffloading -AutoSize # want False4. Persistence and timeouts#
Leave persistence off; Microsoft notes that affinity reduces load-balancer capacity. Make idle timeouts generous: Outlook, ActiveSync and EWS notifications hold long-lived connections, and a short timeout appears as random disconnects.
5. SMTP#
If ports 25 or 587 go through the VIP with source NAT, Exchange sees the load balancer's address. Relay connectors that trust RemoteIPRanges can't identify applications any more: relay fails with 5.7.54, or, if you add the load balancer's IP, everything behind the VIP can relay. Preserve the client source IP or give relaying applications a separate path (see the relay guide).
6. Kerberos#
Several servers answering one namespace need an alternate service account (ASA). If the namespace SPN sits on one computer account, clients routed to another server log KRB_AP_ERR_MODIFIED.
Symptoms of a bad VIP#
| What you see | Usual load-balancer cause | First check |
|---|---|---|
HTTP Error 503. The service is unavailable. for some OWA/ECP users | Monitor not on healthcheck.htm, or no receive string, so a server with a failed protocol stays in the pool | Per-server probe test below |
Outlook: The connection to Microsoft Exchange is unavailable. Outlook must be online or connected to complete this action., or Disconnected | MAPI pool down, layer 4 probe on another virtual directory, idle timeout too short | /mapi/healthcheck.htm per server; VIP timeouts (Outlook guide) |
| Password prompts after CU14 or enabling Extended Protection | SSL offloading, or a different certificate on the load balancer | Re-encrypt with the same certificate (Extended Protection) |
| OWA sign-in page keeps returning | Servers behind the VIP have different certificates, so the next server can't read the cookie | Compare thumbprints with Get-ExchangeCertificate |
The Kerberos client received a KRB_AP_ERR_MODIFIED error from the server (System log, Event ID 4) | Namespace SPN on a computer account, no ASA | ASA credential on every server |
550 5.7.54 SMTP; Unable to relay recipient in non-accepted domain for an app | Source NAT hides the app's IP | SMTP receive protocol log |
Verify#
Probe every server by IP with your namespace name (use curl.exe, because curl is an alias in Windows PowerShell):
foreach ($ip in "10.0.0.11","10.0.0.12") {
foreach ($v in "owa","ecp","ews","mapi","Microsoft-Server-ActiveSync","oab","autodiscover") {
$code = curl.exe -s -o NUL -w "%{http_code}" --resolve "mail.contoso.com:443:$ip" "https://mail.contoso.com/$v/healthcheck.htm"
"{0,-12} {1,-28} {2}" -f $ip, $v, $code
}
}
Get-ServerComponentState -Identity EX01 | Where-Object { $_.State -ne "Active" }
Get-HealthReport -Identity EX01 | Where-Object { $_.AlertValue -ne "Healthy" }Good: 200 everywhere, matching the load balancer's member status, no inactive components. Then, in a maintenance window, set ServerWideOffline to Inactive on one server: every monitor should mark it down within a few probe intervals, and come back when you set it Active again.
Tips & gotchas#
- Probe the servers, not the VIP, and keep probes per pool so one failed protocol doesn't drain the server.
- After renewing the certificate, update the load balancer's copy too when bridging (certificate renewal).
- A component left Inactive after an update looks like a load-balancer fault: the monitors are right to pull the server.
- Read Managed Availability health sets before blaming the appliance for a server it keeps marking down.
References#
- Load balancing in Exchange Server (Microsoft Learn)
- Exchange Server support for Windows Extended Protection (Microsoft Learn)
- K000158134: HTTP/HTTPS Health monitor configuration and troubleshooting (F5)
- Extended Protection for Microsoft Exchange Server (KB5017260) (Progress Community, LoadMaster)

