
What is the difference between an A record and a CNAME record?
The difference between an A record and a CNAME record is what they point to. An A record points a hostname directly at an IPv4 address, such as 192.0.2.10. A CNAME record points a hostname at another hostname, such as shops.example.net, and the resolver then looks up that name to find the address. Use an A record when you know the server's IP address and control it, and always for the bare domain. Use a CNAME when a subdomain should follow a hostname managed by someone else, such as a SaaS platform or CDN, so that their address changes don't require any work from you.
Both records end in the same result, a browser connecting to an IP address, so it's easy to treat them as interchangeable. They aren't. They differ in where they're allowed, how they're resolved, who controls the final address, and how they behave when things change. This article compares the two side by side, walks through the same name resolved both ways, gives a practical decision guide with real scenarios, and explains how to switch a name from one to the other without an outage.
The Core Difference in One Example
Here's the same hostname configured both ways. As an A record:
shop.example.com. 3600 IN A 203.0.113.80
As a CNAME:
shop.example.com. 3600 IN CNAME shops.example.net.
The A record is a final answer: "shop.example.com is at 203.0.113.80". The CNAME is a referral: "shop.example.com is the same as shops.example.net; go and ask about that instead".
You can see this difference in a lookup. With the A record:
dig shop.example.com A +noall +answer
shop.example.com. 3600 IN A 203.0.113.80
With the CNAME, the answer includes both the alias and the target's addresses:
dig shop.example.com A +noall +answer
shop.example.com. 3600 IN CNAME shops.example.net.
shops.example.net. 300 IN A 203.0.113.80
shops.example.net. 300 IN A 203.0.113.81
In the second case, you control only the first line. The provider controls the rest, including which addresses are returned and how long they're cached.
A Record vs CNAME: Side-by-Side Comparison
| Aspect | A record | CNAME record |
|---|---|---|
| Points to | An IPv4 address | Another hostname |
| IPv6 | Needs a separate AAAA record | Follows whatever A and AAAA records the target has |
| Allowed at the bare domain | Yes | No |
| Can share a name with other records (MX, TXT, etc.) | Yes | No |
| Multiple values per name | Yes, several A records | No, only one CNAME per name |
| Who controls the final IP address | You | The owner of the target name |
| Extra lookups on a cache miss | None | One or more, to resolve the target |
| Updating after a server move | You must change the record | Nothing to do if the target owner updates their records |
| Valid as an MX or NS target | Yes (the hostname must have A or AAAA records) | No |
| Typical use | Your own servers, the bare domain, mail and nameserver hostnames | Subdomains on SaaS platforms, CDNs, provider-managed DKIM or validation records |
What an A Record Gives You
- Directness: One record, one answer, no dependency on anyone else's DNS.
- Flexibility: It can coexist with MX, TXT, CAA and any other record on the same name.
- Placement anywhere: It works at the bare domain and on any subdomain.
- Simple redundancy: Several A records on one name spread traffic across servers.
The cost is that you must keep it accurate. If the server's IP address changes, the record is wrong until you update it.
What a CNAME Gives You
- Hands-off maintenance: The target's owner can change addresses, add IPv6, or move regions, and your name follows automatically.
- Provider-side traffic steering: CDNs and platforms can return different addresses for different visitors behind their hostname.
- One place to update: Several of your own names can alias a single canonical host.
The cost is that the name can't hold anything else, can't be used at the apex, and depends on a second set of nameservers being available.
How to Decide: A Practical Guide
Work through these questions in order. The first one that applies usually decides it.
- Is this the bare domain (
example.com)? Use an A record (plus AAAA for IPv6). If your provider only gives you a hostname, use your DNS provider's ALIAS or flattened CNAME feature if it has one, or point the apex at fixed addresses the provider publishes for that purpose. - Does this name need MX, TXT or other records? Use an A record, because a CNAME can't coexist with them.
- Will this hostname appear in an MX or NS record? Use an A record (and AAAA).
- Did a provider give you a hostname to point at? Use a CNAME. Pinning their current IP in an A record will break when they change it.
- Did a provider give you an IP address? Use an A record with exactly that address.
- Is it a server you run with a stable, reserved IP address? Use an A record.
- Do several of your own names run on the same host? Give the host one A record and point the other names at it with CNAMEs, or simply use A records on each if you manage DNS as code and updating them together is easy.
Real-World Scenarios
A Website on Your Own VPS
You run a VPS at 192.0.2.10 with a reserved IPv4 address and an IPv6 address. Both example.com and www.example.com should load the site.
@ 3600 IN A 192.0.2.10
@ 3600 IN AAAA 2001:db8:10::1
www 3600 IN A 192.0.2.10
www 3600 IN AAAA 2001:db8:10::1
A CNAME for www pointing at example.com would also work and saves updating two names when the server moves. Either is fine; the important thing is that the apex uses A and AAAA.
A Shop on a Hosted Commerce Platform
The platform tells you to point shop.example.com at shops.example.net. Use a CNAME:
shop 3600 IN CNAME shops.example.net.
If you looked up shops.example.net, copied its current IP and created an A record instead, the shop would work today and break the next time the platform moved its servers or changed its CDN.
A Subdomain That Also Needs Email
You want support.example.com to load a help desk and receive email at help@support.example.com. The help desk provider offers a CNAME target. Because the name needs MX records, a CNAME isn't possible here. Your options are:
- Use the provider's published IP addresses with A records, if it offers them.
- Receive the email on a different name, such as
help@example.com, and keepsupport.example.comas a CNAME.
The second option is usually simpler and more robust.
A Static Site Behind a CDN
The CDN gives you d111111abcdef8.cloudfront.net for static.example.com. Use a CNAME, because CloudFront returns different addresses depending on the visitor's location and changes them frequently:
static 3600 IN CNAME d111111abcdef8.cloudfront.net.
Performance: Does a CNAME Really Slow Things Down?
A CNAME adds work only on a cache miss. When a resolver hasn't cached anything for the name, it has to resolve your CNAME and then resolve the target, which may involve different nameservers. When both parts are cached, the answer comes back in one response, just as fast as an A record.
You can measure the difference yourself by querying a name that isn't cached yet and then repeating the query:
dig @1.1.1.1 static.example.com A | grep "Query time"
dig @1.1.1.1 static.example.com A | grep "Query time"
;; Query time: 61 msec
;; Query time: 3 msec
For a popular CDN or SaaS target that's constantly being resolved by other users, the target is almost always already cached, so the real-world overhead is often close to zero. For a rarely used target with a short TTL, the extra lookup is more noticeable. In practice, the reliability benefit of following the provider's hostname far outweighs a few milliseconds.
Switching a Name From One Type to the Other
Because a CNAME can't coexist with an A record on the same name, you can't simply add the new record and then remove the old one. You have to replace one with the other.
In a Dashboard
- Lower the TTL on the existing record a day ahead, for example to 300 seconds, so the change spreads quickly.
- Delete the old record and create the new one straight away. Some dashboards let you change the type of an existing record in place, which does both in one step.
- Check the authoritative answer, then a public resolver.
There's a brief moment between the delete and the create when the name doesn't exist on your nameservers. In practice it's a few seconds, but any resolver that asks during that window will cache a negative answer for the length of your SOA's negative caching TTL. If that matters, use a method that changes both atomically.
Atomically With the Route 53 API
Amazon Route 53 applies every change in a single change batch atomically, so you can delete an A record and create a CNAME in one request with no gap:
aws route53 change-resource-record-sets \
--hosted-zone-id Z0123456789EXAMPLE \
--change-batch '{
"Comment": "Move shop from A record to CNAME",
"Changes": [
{
"Action": "DELETE",
"ResourceRecordSet": {
"Name": "shop.example.com",
"Type": "A",
"TTL": 300,
"ResourceRecords": [{"Value": "203.0.113.80"}]
}
},
{
"Action": "CREATE",
"ResourceRecordSet": {
"Name": "shop.example.com",
"Type": "CNAME",
"TTL": 3600,
"ResourceRecords": [{"Value": "shops.example.net"}]
}
}
]
}'
For a DELETE, the values must exactly match the existing record, including the TTL, or the whole batch is rejected and nothing changes.
In a Zone File
If you run BIND, editing the zone file and reloading it swaps the records in one step, because the server loads the new version of the zone as a whole:
; Before
shop 300 IN A 203.0.113.80
; After
shop 3600 IN CNAME shops.example.net.
Remember to increase the SOA serial so secondary nameservers pick up the change, then reload:
named-checkzone example.com /etc/bind/zones/db.example.com && sudo rndc reload example.com
Checking Which Type a Name Uses
To find out whether an existing name is an A record or a CNAME, ask for the CNAME type explicitly:
dig www.example.com CNAME +short
If this prints a hostname, the name is a CNAME. If it prints nothing, query for A records:
dig www.example.com A +short
A quick script can audit several names at once. This Python example uses dnspython (pip install dnspython):
import dns.resolver
names = ["example.com", "www.example.com", "shop.example.com", "static.example.com"]
for name in names:
try:
target = dns.resolver.resolve(name, "CNAME")[0].target.to_text()
print(f"{name:<22} CNAME -> {target}")
except dns.resolver.NoAnswer:
try:
addrs = ", ".join(r.address for r in dns.resolver.resolve(name, "A"))
print(f"{name:<22} A -> {addrs}")
except dns.resolver.NoAnswer:
print(f"{name:<22} no A or CNAME record")
except dns.resolver.NXDOMAIN:
print(f"{name:<22} does not exist")
example.com A -> 192.0.2.10
www.example.com CNAME -> example.com.
shop.example.com CNAME -> shops.example.net.
static.example.com CNAME -> d111111abcdef8.cloudfront.net.
FAQ: A Record vs CNAME
Neither affects search rankings directly. Search engines see the content served at your hostname, not which record type DNS uses. Choose the record that keeps the site reliably reachable.
No. A name with a CNAME can't have any other records. Delete the A record before adding the CNAME, or the other way round.
Either works. A CNAME from www to your bare domain means you only update the apex when your server moves, while A records on both are equally valid and avoid an extra lookup. If www points to a hosting platform, use the CNAME the platform provides.
Because the provider wants to be able to change its IP addresses without asking every customer to update DNS. A CNAME lets your hostname follow the provider's own records automatically.
You can, but it's risky. The provider can change that address at any time, and your A record would then point at the wrong server. Use the hostname they give you unless they also publish stable IP addresses.
Use your DNS provider's ALIAS, ANAME or CNAME flattening feature if it has one. Otherwise, ask the host for IP addresses to use at the apex, or redirect the bare domain to www and use a CNAME on www.
Conclusion
An A record and a CNAME record both get visitors to a server, but in different ways. An A record answers with an IP address that you control, works anywhere including the bare domain, and can sit alongside other records. A CNAME answers with another hostname, hands control of the final address to that name's owner, and must stand alone on a subdomain.
Choose an A record for the apex, for names that need email or other records, and for servers whose addresses you manage. Choose a CNAME when a provider gives you a hostname, so their changes never become your outage. When you need to switch between the two, lower the TTL first and replace the records in one step, and check the result with dig before moving on.


