DNS-01 vs HTTP-01: picking the ACME challenge that scales

Every ACME integration chooses HTTP-01 or DNS-01 first — and often never revisits the decision. HTTP-01 is simpler on paper. DNS-01 scales to wildcards and split-horizon DNS. The wrong choice shows up as intermittent renewal failures that correlate with TTL, CDN caching, or firewall rules nobody documented.

HTTP-01: when it works

The CA fetches http://hostname/.well-known/acme-challenge/token on port 80. You need a reachable web server, predictable routing through load balancers, and no CDN rules that swallow unknown paths. Good fit for single-hostname App Service or nginx VMs with public IPv4. Breaks when you terminate TLS only on 443 and block 80, when Kubernetes Ingress uses different classes per environment, or when geo-DNS sends the validator to the wrong region.

DNS-01: wildcards and internals

DNS-01 proves control by publishing a TXT record at _acme-challenge.hostname. Required for wildcard certs. Works for internal services if the CA can resolve your public DNS zone — you do not need the app reachable from the internet. Requires API access to the authoritative provider with scoped credentials and idempotent record cleanup after success.

Plan propagation windows with the DNS-01 challenge planner: domain count, current TTL, and buffer minutes before the CA polls.

Propagation is the silent killer

Automation creates the TXT record and immediately tells the CA to validate. Resolvers with cached NXDOMAIN or stale TTL miss the record. Fix: lower TTL to 60–300 seconds during migration, add retry with exponential backoff, and verify propagation from multiple resolver locations before finalize. Your runbook should state maximum wait time — not "DNS is eventually consistent."

Security tradeoffs

DNS API keys are high value. Store them in a vault, rotate quarterly, and restrict to TXT on _acme-challenge subzones where possible. HTTP-01 exposes a temporary token on the web tier — acceptable for public sites, risky if .well-known is misconfigured to serve from shared storage with directory listing. Neither method replaces monitoring: alert on challenge failure rate, not just cert expiry.

Hybrid estates

Use HTTP-01 for public marketing hostnames behind a simple CDN. Use DNS-01 for *.api.example.com, multi-region Kubernetes, and anything behind WAF rules that block automated scanners. Document the mapping in your certificate inventory — reviewers should see challenge type per SAN, not discover it in a failed order log.

After picking DNS-01 at scale, sanity-check renewal dates with the ACME renewal timeline so cron jobs respect both CA polling windows and your provider's API rate limits.