Custom Domains
Domain and DNS questions come up because they are the part of deployment that most developers have never actually done.
1. DNS Basics
| Record | Points to | Use |
|---|---|---|
| A | An IPv4 address | Apex domain (example.com) |
| AAAA | An IPv6 address | Apex domain, IPv6 |
| CNAME | Another domain name | Subdomains (www.example.com) |
| TXT | Arbitrary text | Domain verification, SPF, DKIM |
| MX | A mail server | |
| NS | Nameservers | Delegating who answers for the zone |
The Apex Domain Problem
The DNS spec does not allow a CNAME at the apex (example.com). A CNAME replaces all other records at that name, which would break your MX records — you'd lose email.
That is why platforms give you an A record for the apex and a CNAME for www.
Some DNS providers offer ALIAS / ANAME / "CNAME flattening" (Cloudflare) — a CNAME-like record at the apex that resolves server-side. If your provider supports it, use it: the platform can change IPs without breaking you.
Knowing why the apex can't be a CNAME is a genuinely good interview answer — most people have only followed the instructions.
2. Adding a Domain to Vercel
- Project → Settings → Domains → add
example.com - Vercel shows the records to create
- Add them at your registrar (Namecheap, GoDaddy, Cloudflare)
- Wait for propagation
- Vercel issues a TLS certificate automatically
Typical Records
Type Name Value
A @ 76.76.21.21
CNAME www cname.vercel-dns.comOr Delegate Nameservers
Point your registrar at Vercel's nameservers and Vercel manages the whole zone. Simpler, but you lose direct control of MX and other records — fine for a project domain, less so for a company domain that also handles email.
3. Propagation
DNS changes are not instant. Resolvers cache records for the TTL duration.
| TTL | Meaning |
|---|---|
| 300 (5 min) | Fast changes, more DNS queries |
| 3600 (1 hour) | Common default |
| 86400 (24 hours) | Slow to change, fewest queries |
The Migration Trick
Lower the TTL to 300 a day before you migrate. Then the switch propagates in minutes instead of a day. Raise it again afterwards.
This one detail is the difference between a planned migration and a stressful one.
Checking
dig example.com A +short
dig www.example.com CNAME +short
nslookup example.com 8.8.8.8 # query a specific resolverYour own machine caches too — dig against 8.8.8.8 shows what the wider internet sees, not what your laptop remembers.
4. www vs Apex — Pick One
Serve one canonical hostname and 301 redirect the other.
example.com → redirects to → www.example.comor the reverse. Vercel does this in Domains settings.
Why It Matters
| Reason | Detail |
|---|---|
| SEO | Two URLs serving identical content splits ranking signals |
| Cookies | A cookie on the apex is sent to every subdomain, including a compromised one |
| Analytics | Traffic split across two hostnames |
| Certificates | Fewer names to manage |
The cookie point is the one people miss and the strongest technical argument for www: a cookie set on example.com is sent to staging.example.com, blog.example.com and anything else. Setting it on www.example.com scopes it to that host only.
5. HTTPS and Certificates
Vercel provisions and renews Let's Encrypt certificates automatically. Nothing to do.
Requirements
- DNS must point at Vercel before the certificate can be issued (domain validation)
- If you use Cloudflare, set SSL mode to Full (strict). "Flexible" means Cloudflare talks HTTP to your origin, which is unencrypted on the last hop and can cause redirect loops
HSTS
{
key: "Strict-Transport-Security",
value: "max-age=63072000; includeSubDomains; preload",
}Tells browsers to only ever use HTTPS for this domain.
Warning worth stating: HSTS is hard to undo. Once a browser has cached the header, it refuses HTTP for max-age seconds — you cannot fix a broken certificate by falling back to HTTP. Add preload only when you are certain every subdomain has HTTPS working.
6. Redirects
Domain-Level (Vercel Settings)
Set one domain as the redirect target of another. Handled at the edge, before your app runs — the fastest option.
Application-Level
// next.config.ts
async redirects() {
return [
{ source: "/old-blog/:slug", destination: "/blog/:slug", permanent: true },
{
source: "/:path*",
has: [{ type: "host", value: "old-domain.com" }],
destination: "https://new-domain.com/:path*",
permanent: true,
},
];
}301 vs 302
| 301 Permanent | 302 Temporary | |
|---|---|---|
| SEO | Passes ranking to the target | Keeps ranking on the original |
| Browser caching | Cached aggressively | Not cached |
| Use for | Domain moves, permanent URL changes | A/B tests, temporary maintenance |
A wrong 301 is painful. Browsers cache it hard, so users who hit the bad redirect keep following it even after you fix it. Use 302 while you're unsure, then switch to 301 once the destination is final.
permanent: true in Next.js means 308, false means 307 — the modern equivalents that preserve the HTTP method.
7. Subdomains
www.example.com → the marketing site
app.example.com → the application
api.example.com → the backend
docs.example.com → documentation
staging.example.com → stagingEach can be a separate Vercel project, or a different host entirely. Add a CNAME per subdomain.
Wildcard Domains
*.example.com for multi-tenant apps (acme.example.com, globex.example.com). Requires nameserver delegation to Vercel for the wildcard certificate, and you read the tenant from the Host header in proxy.ts.
Cookies Across Subdomains
// Shared across all subdomains — convenient, and a wider blast radius
res.cookie("session", token, { domain: ".example.com" });
// Scoped to one host — safer
res.cookie("session", token, { /* no domain — defaults to the exact host */ });Security note: a cookie on .example.com is sent to every subdomain. If any subdomain is compromised — an old staging box, a third-party-hosted blog.example.com — it receives your session cookie. Scope cookies as narrowly as the product allows.
8. Email and the Apex
A very common real-world break: adding a domain to a hosting platform and losing email.
MX @ 10 mx1.your-email-provider.com
TXT @ "v=spf1 include:_spf.provider.com ~all"- MX records live on the apex alongside the A record — they coexist fine
- If you delegate nameservers to Vercel, you must recreate MX, SPF, DKIM and DMARC records there, or email silently stops
- This is why a CNAME at the apex is forbidden — it would wipe the MX records
Screenshot the existing DNS zone before changing nameservers. Recovering a mail configuration from memory is not fun.
9. Troubleshooting
| Symptom | Cause |
|---|---|
| "Invalid Configuration" in Vercel | DNS records don't match; check for a typo or a leftover old A record |
Domain works, www doesn't | Missing CNAME for www |
| Certificate pending for hours | DNS hasn't propagated, or a CAA record blocks Let's Encrypt |
| Redirect loop | Cloudflare SSL set to "Flexible" instead of "Full (strict)" |
| Old site still showing | Local DNS cache or browser cache — check with dig @8.8.8.8 |
| Email stopped after migration | MX records not recreated after nameserver delegation |
| Works in incognito, not normally | Cached 301 redirect in the browser |
CAA Records
CAA @ 0 issue "letsencrypt.org"A CAA record restricts which certificate authorities may issue for your domain. If one exists and doesn't include Let's Encrypt, certificate issuance silently fails. An obscure cause that wastes hours — worth knowing it exists.