The short answer

An A record says “this name lives at this IPv4 address”. AAAA is the same thing for IPv6. A CNAME says “this name is really that other name; go ask about that one instead”.

Use a CNAME when someone else controls the addresses: a CDN, a SaaS product, a hosting platform. Use A/AAAA when you control the addresses yourself, and always at the root of your domain (example.com), where a CNAME isn’t allowed.

That covers most decisions. The rest of this page is about why, and about the situations where the short answer gets people into trouble.

What each record does on the wire

An A record is one hop: name in, address out.

$ dig +noall +answer api.example.com A
api.example.com.        3600    IN      A       203.0.113.10

A CNAME returns a chain:

$ dig +noall +answer shop.example.com A
shop.example.com.            3600  IN  CNAME  stores.platform.example.net.
stores.platform.example.net.  300  IN  A      198.51.100.7

You asked for an A record and got two answers. The recursive resolver (your ISP’s, 1.1.1.1, 8.8.8.8) saw the CNAME, restarted the lookup at the target name, and returned the whole chain. Your browser didn’t do any extra work. nslookup -type=CNAME shop.example.com shows the same thing as “canonical name = stores.platform.example.net.”

Two things follow from this, and they explain almost every CNAME rule.

A CNAME redirects every query type, not just addresses. Ask for AAAA, TXT or MX at shop.example.com and the resolver answers from stores.platform.example.net. That’s why a CNAME covers IPv4 and IPv6 at once without you adding anything, and it’s also why a CNAME can’t live next to other records (more below).

Each link in the chain has its own TTL. In the example, resolvers cache your CNAME for an hour but the platform’s A record for only five minutes. The platform can move its servers and your visitors follow within five minutes, without you touching your zone. That’s the real reason platforms ask you for a CNAME instead of an IP: it keeps the addresses their problem.

Which one to use

SituationUseWhy
Root domain (example.com)A/AAAA, or the provider’s ALIAS/flatteningA CNAME isn’t allowed at the zone apex
Subdomain pointing at a CDN, SaaS or hosting platformCNAME, exactly as the provider documents itThey can change IPs; it’s often how they verify the domain and issue its certificate
Subdomain on your own server with a stable IPA/AAAAIndirection buys you nothing
www on the same server as the rootA/AAAA on the root, then either a CNAME from www to the root or the same A/AAAA on bothA CNAME means one place to change when the IP moves
A name that also needs MX or TXTA/AAAAA CNAME can’t share its name
The hostname your MX record points toA/AAAAMX and NS targets must not be aliases (RFC 2181)

If a provider tells you which record to create, do what they say. They know what their edge expects, and some of them check for the exact CNAME before they will issue a certificate for your name.

Why you can’t have a CNAME at the root

RFC 1034 (section 3.6.2) says that if a CNAME is present at a name, no other data should be present there. RFC 2181 restates it, and DNSSEC later carved out an exception only for its own signature records.

The root of every zone must have an SOA record and NS records. So the root already holds other data, and a CNAME there contradicts the zone’s own structure. In real zones the root also holds MX records, the SPF TXT record and a pile of verification TXT records, which makes it worse.

BIND won’t even load such a zone: named-checkzone reports CNAME and other data. Some hosted DNS dashboards used to accept the combination anyway, and then behaviour depends on what the server chooses to return. The failure people notice is usually mail: a resolver that receives the CNAME follows it, so an MX query for your domain gets answered with the target’s MX records, which belong to someone else or don’t exist.

What to do instead

ALIAS, ANAME or CNAME flattening. Many DNS providers offer a record you configure like a CNAME but which answers like an A/AAAA record: the provider resolves the target itself and returns the addresses. Cloudflare calls this CNAME flattening and applies it automatically at the root. Others call it ALIAS or ANAME. Route 53 has “alias” records that do the same thing, but only for AWS resources and other records in the same hosted zone.

None of these are standard DNS record types. They exist inside one provider. If you move DNS providers, check that the new one supports it before you switch, or the record won’t come across.

There is one trade-off. With flattening, the provider looks up the target from its own servers, not from the visitor’s resolver. A CDN that chooses an edge location based on where the DNS query came from may see the DNS provider instead of the visitor. Whether that matters depends on the provider and the CDN, so if edge placement matters to you, ask both.

Check the result: you should see A/AAAA records at the root, not a CNAME.

$ dig +noall +answer example.com A
example.com.            300     IN      A       198.51.100.7

The platform’s published addresses. Many hosting platforms document fixed IP addresses for root domains (GitHub Pages, for example, publishes A and AAAA records for apex domains). Use them exactly as listed, and look at their docs again if the site ever stops resolving.

Redirect the root to www. Point www at the platform with a CNAME, and let the root answer with a plain server or your provider’s redirect feature that sends a 301 to https://www.example.com. Remember the redirect only happens after TLS succeeds, so the root still needs a valid certificate of its own.

The “no other records” rule applies to subdomains too

People meet this rule at the root first, but it bites on subdomains just as often.

A service asks you to prove ownership with a TXT record at docs.example.com, and docs is already a CNAME to your documentation host. Your dashboard refuses to add it, or accepts it and the check never passes, because a TXT query at that name follows the CNAME:

$ dig +noall +answer docs.example.com TXT
docs.example.com.                  3600  IN  CNAME  docs-site.hosting.example.net.
docs-site.hosting.example.net.      300  IN  TXT    "v=spf1 include:_spf.hosting.example.net ~all"

That TXT record is the host’s, not yours. Most services offer verification on a separate name such as _service-verify.docs.example.com for exactly this reason. Use that if it’s offered.

The same goes for mail. If support.example.com should receive email (MX) and also show a website hosted on a platform, it can’t be a CNAME. Use the platform’s A/AAAA records for that name, or receive the mail at a different name.

Mistakes that look fine in the dashboard

An IP address in a CNAME. Some dashboards accept 203.0.113.10 as a CNAME target without complaint. Resolvers then look for a host named 203.0.113.10. (or 203.0.113.10.example.com. if the dashboard appends your zone), find nothing, and the name returns NXDOMAIN.

A missing trailing dot in a zone file. In BIND syntax, www IN CNAME app.platform.net without a final dot becomes app.platform.net.example.com.. Write app.platform.net.. Web dashboards usually handle this for you; hand-edited zone files don’t.

MX or NS records pointing at a CNAME. RFC 2181 (section 10.3) says MX and NS targets must have address records directly, not be aliases. Plenty of mail servers tolerate it anyway, which is exactly why it goes unnoticed until one sender doesn’t. Give your mail host an A/AAAA record.

Forgetting AAAA when you switch from CNAME to A. A CNAME covered IPv6 automatically. With A records, IPv6 is a separate record you have to maintain, and a stale AAAA sends IPv6 visitors to an old server while IPv4 users see the new one. The A/AAAA checklist covers how to spot that.

Dangling CNAMEs. You delete an app, storage bucket or landing page on a platform but leave promo.example.com pointing at it. On some platforms anyone can then create a resource with that same name and serve their content on your subdomain. When you delete the resource, delete the DNS record in the same change.

Long chains across several providers. One or two hops is normal, and CDNs routinely use a couple internally. But every link is another provider that has to be up and another TTL to wait out when something changes. If your chain runs through three companies, ask whether it needs to.

Checking what you actually have

From a terminal:

dig +noall +answer www.example.com A
dig +noall +answer www.example.com AAAA
dig +short www.example.com CNAME

# straight from your authoritative server, bypassing every cache
dig @ns1.your-dns-provider.example www.example.com A +norecurse

The DNS lookup shows every record type for a name with its TTL, so you can see at a glance whether a name is a CNAME, has A/AAAA records, or (wrongly) seems to have both.

If you just changed a record from A to CNAME or the other way round, resolvers keep the old answer until its TTL runs out. The propagation check compares public resolvers so you can see who has switched, and the TTL guide explains how to shorten that wait next time.

If you pointed a CNAME at a platform and the site now fails with a certificate name error, the platform usually hasn’t been told about your domain yet. That’s cause 4 in the ERR_CERT_COMMON_NAME_INVALID guide, and the SSL check shows which certificate the platform is actually serving for your name.

Check your own domain now

Free, no sign-up. Runs the exact check this guide describes and shows what to fix.