When deploying applications on platforms like Heroku, you'll encounter this fundamental recommendation: avoid using naked domains (e.g., example.com) and use subdomains (www.example.com) instead. This isn't just arbitrary advice - it stems from technical limitations in DNS architecture and cloud infrastructure design.
Naked domains pose these specific challenges:
- No CNAME at the apex: DNS protocol prevents CNAME records at the zone apex (RFC 1034)
- Hardcoded IP dependencies: A-records require static IP addresses, conflicting with cloud elasticity
- No failover capability: Unlike CNAMEs, A-records can't dynamically route to backup infrastructure
Consider how Heroku's routing layer works:
Client Request -> DNS -> Heroku Router -> Dyno
↑
Static A-records break here
Heroku's edge routers use dynamic IP pools that change frequently. A-records would require constant updates, creating:
- DNS propagation delays during scaling events
- Potential downtime during IP changes
- Manual maintenance overhead
Here are proven approaches used by major platforms:
1. ALIAS/ANAME Records (DNS Provider Solution)
Modern DNS providers offer pseudo-records that behave like CNAMEs at the apex:
; Cloudflare configuration example
example.com. ALIAS proxy-ssl.herokudns.com.
www CNAME proxy-ssl.herokudns.com.
2. HTTP 301 Redirect
Configure your naked domain to redirect to the subdomain:
# Express.js redirect middleware
app.use((req, res, next) => {
if(req.hostname === 'example.com') {
return res.redirect(301, 'https://www.example.com' + req.path);
}
next();
});
3. Reverse Proxy Setup
For on-premise hybrid solutions:
# Nginx configuration
server {
listen 80;
server_name example.com;
return 301 https://www.example.com$request_uri;
}
server {
listen 80;
server_name www.example.com;
location / {
proxy_pass https://your-app.herokuapp.com;
}
}
StackOverflow.com works with an A-record because:
- They maintain their own infrastructure with static IPs
- They've implemented sophisticated anycast routing
- They accept the operational overhead of manual IP management
For Heroku apps, always use:
heroku domains:add www.yourdomain.com
heroku domains:wait www.yourdomain.com
Then configure your DNS to point the www subdomain to Heroku's DNS target.
When you configure a naked domain (e.g., example.com) via DNS A-records, you're hardcoding IP addresses into your DNS configuration. This creates several critical limitations in dynamic cloud environments:
# Example of problematic A-record configuration
example.com. IN A 192.0.2.1
example.com. IN A 192.0.2.2
Heroku's infrastructure relies on elastic load balancing and automatic scaling. When you use a subdomain (www.example.com) with CNAME records, you gain:
- Automatic IP failover when Heroku reroutes traffic
- Built-in load balancing across multiple availability zones
- Zero-downtime infrastructure changes behind the scenes
# Recommended CNAME configuration
www.example.com. IN CNAME example.herokudns.com.
Consider these scenarios where naked domains fail:
Scenario | Naked Domain Impact | Subdomain Solution |
---|---|---|
Heroku IP change | Requires manual DNS updates (downtime) | CNAME automatically follows new endpoint |
DDoS attack | Static IPs make targeting easier | Cloud provider absorbs attack |
Region failure | Manual DNS failover required | Automatic geo-routing |
If you absolutely need naked domain support, use a DNS provider that offers ALIAS or ANAME records:
// Cloudflare example using CNAME flattening
example.com. IN CNAME example.herokudns.com.
Alternatively, implement a 301 redirect at the application level:
// Node.js redirect example
app.get('/', (req, res) => {
if(req.hostname === 'example.com') {
return res.redirect(301, 'https://www.example.com' + req.path);
}
// ... normal routing
});
StackOverflow.com operates on dedicated infrastructure with:
- Stable, long-term IP assignments
- On-premise load balancing capabilities
- Engineering team managing DNS manually
For most cloud-native applications following the 12-factor methodology, subdomains provide better operational characteristics in line with platform-as-a-service constraints.