SRV record
An A record gives you an address. It says nothing about which port the service listens on, whether there's a backup, or how to split traffic across several instances — all of which have to be hardcoded somewhere else, usually in a config file that drifts out of date.
An SRV record carries all four: the host, the port, a priority, and a weight.
The name encodes the service
SRV records live at a structured name, not at the domain itself:
_sip._tcp.example.com describes the SIP service over TCP for example.com. The underscores are deliberate — they're not legal in ordinary hostnames, which guarantees a service label can never collide with a real host's name.
That naming is why an SRV lookup is a discovery mechanism rather than just another address record. A client that wants SIP for a domain constructs the name from what it already knows and asks. No configuration file, no hardcoded port.
The four fields
10 60 5060 sip1.example.com.
│ │ │ └── target: the hostname (which still needs an A/AAAA lookup)
│ │ └─────── port
│ └────────── weight
└───────────── priority
Priority works like MX preference: lower wins. A client tries every target at the lowest priority first and only falls back to a higher number when they all fail. In the output above, sip-backup at priority 20 receives no traffic at all while either priority-10 host is reachable — it's a standby, not a third of the pool.
Weight distributes load within one priority level, proportionally. With weights 60 and 40, sip1 should get about 60% of connections and sip2 about 40% — useful when the servers aren't identical, or during a gradual migration where you want to shift traffic in steps by editing one number.
Port is the field that makes SRV genuinely different from everything around it. It means a service can move to a different port without touching a single client.
Target is a hostname, and it must be one — an SRV record pointing at an IP address is invalid. A client always makes two lookups: SRV first, then A or AAAA for the target it selected.
Where you'll actually meet it
SRV never became the general-purpose service discovery mechanism its designers hoped for. HTTP ignores it entirely — browsers do not look up _http._tcp — so websites get none of this. But in specific ecosystems it's load-bearing:
Microsoft Active Directory depends on it completely. Domain controllers publish _ldap._tcp.dc._msdcs.<domain>, and a client that can't resolve those records cannot find a domain controller and cannot log anyone in. "Active Directory is down" is very often "the SRV records are wrong."
Kubernetes publishes an SRV record for every named Service port:
Which is how a client discovers a Service's port without it being in the deployment manifest. Combined with a headless Service, the SRV query returns every pod with its port — the basis for client-side load balancing.
XMPP, SIP, Minecraft, and Matrix all use SRV to let a domain delegate a service to a differently-named host on a non-standard port. It's why chat.example.com:5222 can serve example.com's XMPP without anyone typing the port.
Failover, and what it doesn't give you
The priority/weight model looks like load balancing, and it's worth being precise about how it differs from a real load balancer.
An SRV record is static data. It has no idea whether sip1 is up. Failover to priority 20 happens only because the client tried the priority-10 hosts, failed, and moved on — so the failover is as good as the client's implementation, and clients vary enormously. Some retry properly; some try the first target and give up; some ignore weight entirely and always pick the first.
Which means SRV gives you client-driven failover with no health checking and no guarantee of correct behaviour. A load balancer gives you server-side health checks and a single address clients can't get wrong. SRV's advantage is that it needs no infrastructure at all — the DNS you already have is the whole mechanism.
A worked check
A client can't reach a service that's supposedly published over SRV. Resolve it the way the client does, in both steps:
There's the fault. The SRV record is fine, and its target doesn't resolve — so a client gets a perfectly valid answer pointing at a host it can't find an address for. The failure surfaces as "service discovery is broken," and the actual missing record is an ordinary A record for dc1.
That two-step dependency is the thing to remember about SRV: every SRV record is only as good as the A record its target needs. Deleting a host's A record breaks every SRV record that names it, and nothing in the SRV zone will look wrong.
Practice
- Query the SRV records for a public XMPP or Matrix domain and resolve each target to an address. Note which port each names.
- Given three SRV records with priorities 10, 10, and 20 and weights 30, 70, and 0, describe exactly which host receives traffic under normal conditions and what happens as each fails in turn.
- In a Kubernetes cluster, query the SRV record for a Service and compare the port it reports with the Service's manifest.
- Explain why an SRV record whose target is an IP address is invalid, and what a client would have to do differently for it to work.
Question 2 is worth writing out fully rather than answering in your head — getting the interaction between priority and weight exactly right, including what happens to a weight of 0 at a higher priority, is the part people get wrong.
Every record so far publishes something about a domain for anyone to use. The last one in this module does the opposite — it restricts who is permitted to act on the domain's behalf, and it's the only DNS record whose audience is not a client at all.
Sources
- IETF, RFC 2782 – A DNS RR for specifying the location of services (DNS SRV)
- Kubernetes, DNS for Services and Pods — the SRV records published for named Service ports.