powershelldba.de · Uwe Janke

The AG Listener in SQL Server: What It Is, Why You Need It, and What Happens During Failover

Every application connected to an Availability Group should talk to one name that never changes, no matter which replica is primary. That name is the listener. Here is what it consists of, why connecting to it instead of a node is the whole point of an AG, and exactly what happens to the listener and to your connections when the AG fails over.

What Is an AG Listener?

An Availability Group listener is a virtual network name that clients use to connect to the databases of an Availability Group. It does not belong to any particular server. It always points to whichever replica is currently the primary.

Technically, a listener is made of three parts:

All of this lives in the Windows Server Failover Cluster (WSFC) as resources inside the AG's cluster role: a Network Name resource and one IP Address resource per subnet. The AG resource depends on them, so they always come online together, on the same node. On Linux, Pacemaker plays the same role with a virtual IP resource.

-- Create a listener for an AG that spans two subnets
ALTER AVAILABILITY GROUP [AG_Sales]
ADD LISTENER N'SalesLsnr' (
    WITH IP (
        (N'10.10.1.50', N'255.255.255.0'),   -- subnet of datacenter A
        (N'10.20.1.50', N'255.255.255.0')    -- subnet of datacenter B
    ),
    PORT = 1433
);

Listener name is not the AG name

The AG itself also has a name (AG_Sales above), and the two are easy to mix up, especially in environments where they happen to be identical by convention. They are different things: the AG name is just the name of the cluster role and is not registered in DNS. Only the listener is a network name.

"The network path was not found" on an AG connection? Check first whether you used the AG name instead of the listener name. If the naming convention says both are the same but one AG was set up differently, scripts and jobs fail with exactly this error, and it looks like a network problem when it is just the wrong name.

To see the real listener names and their state:

SELECT ag.name            AS AvailabilityGroup,
       l.dns_name         AS Listener,
       l.port,
       ip.ip_address,
       ip.state_desc      AS IpState      -- ONLINE only on the primary's subnet
FROM sys.availability_groups AS ag
JOIN sys.availability_group_listeners AS l
     ON l.group_id = ag.group_id
JOIN sys.availability_group_listener_ip_addresses AS ip
     ON ip.listener_id = l.listener_id;

Or with dbatools against any replica: Get-DbaAgListener -SqlInstance SQLNODE1.

Why Use the AG Listener?

1. One connection string for every failover

Without a listener, the application connects to SQLNODE1. After a failover, the primary is SQLNODE2, and the application keeps connecting to a server where the database is now a read-only secondary (or not reachable at all). Someone has to change connection strings, configuration files or DNS aliases, under pressure, in the middle of an incident.

With a listener, the connection string says SalesLsnr and never changes. Failover becomes a cluster event, not an application change. This is the main reason a listener exists.

2. Read-only routing

The listener can also send read-only workloads to a readable secondary. A client that connects with ApplicationIntent=ReadOnly to the listener, with an availability database as its initial database, is redirected to a secondary according to the routing list of the current primary. Reporting and other read workloads move off the primary without a second connection string to maintain. Details and pitfalls are in AG Readable Secondaries for Reporting Offload.

3. Multi-subnet and multi-site setups

When an AG spans two datacenters with different subnets, a single IP address cannot follow the primary. The listener holds one IP per subnet and only brings the right one online, so the application still sees one name. Combined with the correct client setting (below), this is what makes cross-site failover workable for applications.

4. Better than a DNS alias

A hand-maintained DNS CNAME to the current primary can do part of this job, but someone (or something) has to update it on every failover, and caching delays the switch. See DNS Aliases for SQL Server for those problems. The listener is updated by the cluster as part of the failover itself.

How the Listener Works During Failover

Here is the sequence when the AG fails over from SQLNODE1 to SQLNODE2, whether planned (manual failover) or automatic after a failure:

  1. The AG role goes offline on the old primary. The cluster takes the AG resource offline on SQLNODE1 (if that node is still alive). Its dependent resources, the listener's network name and IP addresses, go offline too. All open connections through the listener are dropped at this point, and any open transactions on them are rolled back.
  2. The secondary becomes primary. SQLNODE2 takes over the primary role and runs recovery on the availability databases: committed transactions are rolled forward, uncommitted ones rolled back. The databases come online read-write.
  3. The listener comes online on the new primary's node. The cluster brings the IP address resource online on SQLNODE2.
    • Same subnet: the same IP address simply moves to the new node, which announces it on the network. DNS does not change at all.
    • Different subnet: the IP of datacenter A stays offline and the IP of datacenter B comes online. What clients see now depends on DNS registration (next section).
  4. Clients reconnect. The application reconnects to the same listener name and lands on SQLNODE2. Nothing in the application changed, but it does have to reconnect: the listener does not keep sessions alive across a failover.
The listener makes failover transparent for the connection string, not for the session. Every connection open during the failover is broken. Applications need retry logic for the connect and, ideally, for the failed transaction. A failover usually takes seconds, so a few retries with a short delay cover it.

Multi-subnet failover: RegisterAllProvidersIP, TTL and MultiSubnetFailover

With one IP per subnet, two cluster settings on the listener's network name decide what DNS returns:

SettingWhat DNS containsWhat happens on failover
RegisterAllProvidersIP = 1
(default when the listener is created via T-SQL or SSMS)
All listener IPs, online or not DNS never changes. A client that tries all IPs at once connects to whichever one is online, within seconds.
RegisterAllProvidersIP = 0 Only the currently online IP The cluster updates the DNS record. Clients keep using the cached old IP until the record's TTL (HostRecordTTL, default 1200 seconds = 20 minutes) runs out.

The client side of this is the connection string keyword MultiSubnetFailover=True. It tells the driver to try all IP addresses returned for the name in parallel and use the first one that answers. Without it, the driver tries the addresses one after another and may spend most of the connection timeout waiting on the offline IP in the other datacenter, so connections fail or are slow even when nothing is broken.

Server=tcp:SalesLsnr,1433;Database=SalesDb;Integrated Security=SSPI;MultiSubnetFailover=True;

-- Read-only workload, routed to a readable secondary:
Server=tcp:SalesLsnr,1433;Database=SalesDb;Integrated Security=SSPI;MultiSubnetFailover=True;ApplicationIntent=ReadOnly;

Microsoft recommends MultiSubnetFailover=True for every connection to a listener, even on a single subnet, because it also speeds up reconnection after a failover. Current drivers (Microsoft.Data.SqlClient, ODBC Driver 17/18, recent JDBC) support it. For old clients or applications that cannot set the keyword, the usual compromise is RegisterAllProvidersIP = 0 with a shorter HostRecordTTL (often 300 seconds):

# On a cluster node, as administrator
Get-ClusterResource -Name 'AG_Sales_SalesLsnr' |
    Get-ClusterParameter -Name RegisterAllProvidersIP, HostRecordTTL

Get-ClusterResource -Name 'AG_Sales_SalesLsnr' |
    Set-ClusterParameter -Multiple @{ RegisterAllProvidersIP = 0; HostRecordTTL = 300 }
# Takes effect only after the network name resource is restarted:
# that takes the listener offline briefly, so plan it like a failover.

What does NOT move with the listener

The listener moves connections to the new primary. It does not move anything that lives outside the availability databases:

Listener Best Practices

A quick check that a listener resolves and lands on the primary:

Test-NetConnection SalesLsnr -Port 1433

Invoke-DbaQuery -SqlInstance 'SalesLsnr' -Query "SELECT @@SERVERNAME AS ConnectedTo, sys.fn_hadr_is_primary_replica('SalesDb') AS IsPrimary"

The Bottom Line

The AG listener is a virtual network name with one IP per subnet and a port, owned by the cluster and always online on the node that hosts the primary replica. Applications connect to it instead of a server name, so a failover needs no configuration change: the cluster moves the listener together with the primary role, and clients only have to reconnect. Use the listener name (not the AG name), port 1433, MultiSubnetFailover=True and proper retry logic, and keep logins and jobs in sync across replicas, because those do not travel with the listener.

For the bigger picture, see Failover Clustering vs. AlwaysOn and Quorum and Witness: Why Failover Fails and How to Fix It.

← Back to Blog