You're setting up your new blog on Heroku. Their docs tell you to add a CNAME pointing to your-app.herokuapp.com. You open your DNS panel, create www.yourdomain.com as a CNAME, and it works perfectly.
Then you try to do the same thing for the root domain, yourdomain.com, and hit an error: "CNAME records cannot be created for the root domain."
This isn't a Heroku problem. It's not a bug in your DNS provider either. It's a rule baked into the DNS specification itself: a CNAME record can't coexist with other record types at the zone apex. Because the root of your domain must carry records like SOA and NS, a standard CNAME simply isn't allowed there.
Modern DNS providers work around this with features called ALIAS, ANAME, or CNAME flattening. Platforms like Heroku also document how to configure root domain pointing using these mechanisms.
That said, the underlying rule still matters. To understand why this restriction exists, and when it causes real production problems, you need to understand how CNAMEs actually work.
How CNAME Records Work
A CNAME (Canonical Name) record creates an alias. It tells DNS: "Don't answer this query directly. Go look up this other hostname instead."
Here's what happens when someone visits blog.example.com and you have a CNAME pointing to app-123.platform.com:
- Browser asks DNS: "What's the IP for
blog.example.com?" - DNS responds: "I don't have an IP. Look up
app-123.platform.cominstead." - Browser asks DNS: "What's the IP for
app-123.platform.com?" - DNS responds: "That's
203.0.113.45." - Browser connects to
203.0.113.45.
You can see this in action with the dig command on a Linux or MacOS terminal:
dig www.microsoft.com
…
;; ANSWER SECTION:
www.microsoft.com. 2440 IN CNAME www.microsoft.com-c-3.edgekey.net.
www.microsoft.com-c-3.edgekey.net. 187 IN CNAME www.microsoft.com-c-3.edgekey.net.globalredir.akadns.net.
www.microsoft.com-c-3.edgekey.net.globalredir.akadns.net. 187 IN CNAME e13678.dscb.akamaiedge.net.
e13678.dscb.akamaiedge.net. 13 IN A 2.22.197.228
The response includes both the full CNAME chain and the final A record. Notice that multiple lookups happened. Every CNAME adds latency because each one requires an additional DNS query. For users on slow connections or far from your nameservers, that adds up.
Why use a CNAME at all, then? Because cloud platforms can (and do) change IPs without warning. When Heroku moves your app to a new server, app-123.herokuapp.com automatically resolves to the new IP. Your CNAME keeps working. An A record would break until you manually updated it.
The tradeoff is speed versus flexibility. CNAMEs give you automatic IP updates at the cost of an extra lookup on every visit. Understanding the difference between these DNS record types helps you make the right call for your infrastructure.
The Zone Apex Problem
If a DNS name has a CNAME record, it must not have any other record types associated with it.
That rule comes from the original DNS specifications. RFC 1034 describes how CNAME records work and how resolvers process them. Operational guidance is made explicit in RFC 1912, Section 2.4:
A CNAME record is not allowed to coexist with any other data.
The reason is architectural. A CNAME doesn't contain data the way an A or MX record does. It says, "this name is an alias for another host." If other records existed alongside a CNAME, resolvers would face conflicting instructions: follow the alias, or use the local data? The protocol can't do both.
Your root domain, example.com, must have two records to function at all:
- SOA (Start of Authority): Defines who manages the zone and controls how often it refreshes
- NS (Name Server): Points to the nameservers that answer queries for your domain
These aren't optional. Without them, your domain doesn't exist on the internet. Trying to add a CNAME to example.com asks DNS to simultaneously "ignore this name and look elsewhere" and "use these nameservers." That's a contradiction the protocol won't resolve.
There's another consequence worth calling out: email. Your root domain needs MX records to receive mail at user@example.com. Add a CNAME, and those MX records become invalid. Email stops working.
The practical impact hits hardest when you're deploying to platforms like Vercel, Netlify, or GitHub Pages. They give you a hostname like your-project.vercel.app and tell you to point your domain there. For www.example.com, that works fine. For example.com, you're forced to choose between:
- An A record that breaks when the platform changes IPs
- Redirecting all traffic from
example.comtowww.example.com, losing the clean root URL - Giving up on the root domain entirely
None of those options are good.
How name.com's ANAME Record Solves This
name.com solves this with the ANAME record. It's not part of the DNS specification. It's a feature that name.com's nameservers provide specifically to work around the zone apex limitation.
Here's how it works:
- You create an ANAME record in the name.com dashboard pointing to your target hostname, like
app.platform.com - name.com's nameservers periodically resolve that hostname to get its current IP address
- When a query comes in for your domain, name.com returns that IP as a standard A record
- To the rest of the internet, you have a normal A record. But it updates automatically whenever the target hostname changes IPs.
From the browser's perspective, this is a single-step lookup. You get the speed of an A record with the flexibility of a CNAME.
Configuring an ANAME record:
- Log in to your name.com account
- Navigate to your domain's DNS settings
- Add a new record with these settings:
- Type:
ANAME - Host:
@(represents your root domain) - Answer:
your-app.platform.com(your target hostname) - TTL:
300(5 minutes, allowing quick updates)
- Type:
- Save the record
The record goes live within minutes. name.com handles the resolution in the background, checking for IP changes at regular intervals and updating the served A record automatically. Understanding domain propagation will tell you when your changes are visible globally.
The key benefit: you can now point your root domain at a hostname that might change IPs, without violating DNS protocol rules or breaking your email. Your SOA and NS records stay in place, your MX records keep working, and users reach your site at example.com without the www. You can also read more about bare CNAME records and how name.com handles them.
This is the same concept that Cloudflare calls "CNAME Flattening" and AWS Route53 calls an "Alias" record. The implementation differs, but the goal is identical: solve the zone apex CNAME problem.
Common Pitfalls and Conflicts
Even when you're using CNAMEs correctly on subdomains, a few edge cases will break your setup if you're not careful.
MX Records and Wildcard CNAMEs
A common concern is whether a wildcard CNAME conflicts with your email configuration. Consider this setup:
*.example.com. 300 IN CNAME your-app.platform.com.
mail.example.com. 300 IN MX 10 mail-server.com.
This configuration is actually valid.
The CNAME exclusivity rule applies per name, not per wildcard scope. *.example.com and mail.example.com are different owner names in the zone. According to RFC 4592, a wildcard record is only used when no explicit record exists for the queried name. Because mail.example.com has its own MX record, the wildcard CNAME doesn't apply to it.
Problems occur when you attach a CNAME and another record type to the exact same name:
mail.example.com. 300 IN CNAME app.platform.com.
mail.example.com. 300 IN MX 10 mail-server.com.
This is invalid. A name with a CNAME must not have any other records at that same label.
One more thing worth knowing: the host specified in an MX record must ultimately resolve to an A or AAAA record. If mail.example.com is listed as an MX target, it needs its own address record.
TXT Record Conflicts
You can't add a TXT record to a name that already has a CNAME. The exclusivity rule applies to all record types, not just A and MX.
# This is invalid:
app.example.com. 300 IN CNAME platform.com.
app.example.com. 300 IN TXT "verification-code-123"
This causes real problems when a service asks you to verify domain ownership by adding a TXT record to a subdomain that already points to a platform via CNAME. The DNS provider will reject the TXT record outright.
Common workarounds include:
- Verifying the root domain (
example.com) instead - Using a provider-specific verification name like
_verification.example.com - Verifying a different subdomain that isn't already aliased with a CNAME
The rule is simple: if a record is a CNAME, it can't hold any other record types at the same label.
CNAME Loops
Circular references cause queries to fail entirely.
# This creates an infinite loop:
a.example.com. 300 IN CNAME b.example.com.
b.example.com. 300 IN CNAME a.example.com.
When a resolver tries to look up a.example.com, it follows the CNAME to b.example.com, which points back to a.example.com. Most resolvers detect this after a few iterations and return an error. The site becomes unreachable.
This seems obvious in a two-record example, but it happens accidentally in complex setups where subdomains point to other subdomains across different zones. Always trace the full chain before deploying changes. Use the DNS connectivity troubleshooting tools to verify your configuration before pushing it live.
Long CNAME Chains
While not technically invalid, long CNAME chains hurt performance.
# Each step adds latency:
app.example.com. 300 IN CNAME lb.platform.com.
lb.platform.com. 300 IN CNAME region-us.platform.com.
region-us.platform.com. 300 IN A 203.0.113.45
That's three DNS lookups instead of one. Each lookup can take 50-100ms depending on network conditions. For users on mobile networks or in regions far from your nameservers, this adds up fast. Keep CNAME chains as short as possible.
Choosing the Right Record Type
Here's a quick reference for the most common scenarios:
| Scenario | Record Type | Example |
|---|---|---|
| Subdomain pointing to IP address | A Record |
blog.example.com → 203.0.113.45
|
| Subdomain pointing to hostname | CNAME |
blog.example.com → app.platform.com
|
| Root domain pointing to IP address | A Record |
example.com → 203.0.113.45
|
| Root domain pointing to hostname | ANAME |
example.com → app.platform.com
|
| IPv6 address | AAAA Record |
example.com → 2001:0db8::1
|
| Email server | MX Record |
example.com → mail.example.com
|
| Domain verification | TXT Record |
example.com → "verification-code"
|
A quick checklist before you push any DNS changes:
- If the record is for your root domain and needs to point to a hostname, use an ANAME
- If the record is for a subdomain that also needs MX or TXT records, use an A record instead of a CNAME
- If you're setting up a wildcard catch-all, confirm it doesn't conflict with specific subdomains you need for email or domain verification
- If your platform (Heroku, Vercel, Netlify) provides both a hostname and IP addresses, prefer the hostname with an ANAME or CNAME so you get automatic updates
The most common mistake is trying to use a CNAME at the root domain. The second most common is using a CNAME on a subdomain that also needs to receive email. Both come from the same RFC 1034 rule: CNAMEs must be the only record for that name.
For developers automating DNS management, the name.com API gives you programmatic access to create DNS records, update records, and list all records for your domains without touching the dashboard.
Final Thoughts
CNAMEs follow strict protocol-level rules that made sense in 1987 and still make sense today, even if they create friction in modern workflows. The zone apex restriction exists because your root domain requires SOA and NS records to function, and a CNAME can't legally coexist with those records.
name.com's ANAME records handle the resolution on name.com's nameservers and serve the result as a standard A record. You get automatic IP updates when your platform changes infrastructure, with no protocol violations and no conflicts with your MX or NS records. It's a clean solution to a problem that trips up a lot of engineers the first time they encounter it.

Top comments (0)