Containers and platforms
Heroku Automated Certificate Management (ACM) guide
Heroku Automated Certificate Management (ACM) gets and renews Let's Encrypt certificates for your app's custom domains. Add each domain, point DNS at the herokudns.com target Heroku gives you, and ACM issues the certificate, usually within 45 to 60 minutes.
ACM is free for all apps, and certificates renew one month before they expire. Uploading your own certificate switches ACM off for that app. Steps follow the Heroku Dev Center as of November 2026, with example-app and example.com as examples.
At a glance
| Question | Heroku |
|---|---|
| CA for automatic certificates | Let's Encrypt (via ACM) |
| Price | Included for all applications |
Subdomain (www.example.com) |
CNAME to its <haiku>.herokudns.com DNS target |
Root (example.com) |
ALIAS/ANAME/flattened CNAME to its DNS target; A records are not supported |
| CAA must allow | letsencrypt.org |
| Wildcard via ACM | Not in the Common Runtime docs; Private Space rules below |
| Upload your own certificate | Yes, heroku certs:add (disables ACM) |
| Renewal | Automatic, one month before expiry |
| TLS versions | TLS 1.2 and TLS 1.3 only |
Step 1: Add the domains
Add the root and www names separately; Heroku requires root domains to be added in addition to any subdomains:
heroku domains:add www.example.com -a example-app
heroku domains:add example.com -a example-app
heroku domains -a example-app
Each domain gets its own DNS target, for example whispering-willow-5678.herokudns.com. Your Heroku account must be verified to add domains, and adding domains costs nothing.
Step 2: Point DNS at the targets
Point each name at its own herokudns.com target: a CNAME for www, and an ALIAS, ANAME or flattened CNAME for the root.
| Name | Record | Value |
|---|---|---|
www.example.com |
CNAME |
whispering-willow-5678.herokudns.com |
example.com |
ALIAS, ANAME or flattened CNAME |
hidden-sierra-7936.herokudns.com |
Heroku is explicit that A records are not enough for root domains, because Heroku's IP addresses are dynamic. Providers with ALIAS or ANAME include DNSimple, DNS Made Easy, easyDNS, Namecheap and DreamHost, and Cloudflare flattens a CNAME at the root. If your provider only offers A records at the root, move DNS to one that supports these record types.
Older apps sometimes point at example-app.herokuapp.com or *.herokussl.com. ACM cannot verify those; switch to the herokudns.com target. Also leave out AAAA records, which ACM does not support.
Step 3: Check CAA records
If the domain publishes CAA records, add one that allows Let's Encrypt:
example.com. 3600 IN CAA 0 issue "letsencrypt.org"
Otherwise ACM fails with CAA record prevents issuance, CAA record does not match issuer. If your DNS provider does not support CAA at all, ACM can fail with DNS provider doesn't support CAA. Test with the CAA checker.
Step 4: Enable ACM and watch the status
Enable ACM once DNS points at Heroku, then check the status:
heroku certs:auto:enable -a example-app
heroku certs:auto -a example-app
Generating a certificate usually takes 45 to 60 minutes. The statuses are:
| Status | Meaning |
|---|---|
| Cert Issued | A certificate has been issued for the domain. |
| In Progress | Heroku is verifying the domain's DNS. |
| DNS Verified | DNS is verified; the certificate is being generated. Not finished yet. |
| Waiting | Heroku is waiting to process the certificate. |
| Failing | Heroku cannot verify DNS and will keep trying for up to an hour. |
| Failed | Heroku cannot verify DNS and has stopped trying. |
Wildcards and your own certificate
Wildcard domains can be added to an app with a CNAME from * to the wildcard's DNS target. Heroku's ACM article does not describe ACM issuing wildcard certificates in the Common Runtime. For Private Spaces it says you must upload your own wildcard certificate, that Cedar-generation Private Space apps using ACM cannot have wildcard domains, and that a newer generation of Private Space apps can use ACM with wildcard domains.
To use an EV certificate, another CA or a wildcard certificate, upload it:
heroku certs:add server.crt server.key -a example-app
heroku certs -a example-app
Include the intermediate certificates in server.crt. Uploading a certificate disables ACM; run heroku certs:auto:enable to return to ACM later. Heroku does not let you extract private keys, so keep your own copy. For automatic renewal of a wildcard on a Private Space app, Heroku points to add-ons such as SSL FastTrack or ExpeditedSSL.
Switching from an uploaded certificate to ACM
ACM uses the same DNS configuration as Heroku SSL (SNI), and enabling it on a Private Space app needs no DNS change. While ACM verifies DNS, the app keeps serving the existing certificate. For Private Space apps Heroku documents this order:
- Find the uploaded certificate's name with
heroku certs. - Run
heroku certs:auto:enable. - Wait with
watch heroku certs:autountil the new certificate is issued. Skipping the wait can cause downtime. - Remove the old certificate with
heroku certs:remove --name <name>.
Verify
Once ACM shows the certificate as issued, each domain presents a Let's Encrypt certificate. Check it with the SSL checker, or:
curl ssl.sh/example.com
Then inspect the certificate:
openssl s_client -connect example.com:443 -servername example.com </dev/null 2>/dev/null \
| openssl x509 -noout -issuer -subject -ext subjectAltName -dates
On macOS, avoid curl -k for this check: Heroku notes that on many macOS versions curl with -k does not send SNI.
Renewal
ACM renews certificates one month before they expire and creates a new certificate whenever you add or remove a custom domain. If ACM cannot create a certificate, Heroku sends a notification after three days of attempts. Uploaded certificates are never renewed by Heroku; replace them with heroku certs:update. Let's Encrypt itself stopped sending expiry emails on June 4, 2025, and its default lifetime becomes 64 days on February 10, 2027, so add critical domains to ssl.sh monitoring (in development).
Troubleshooting
Do not turn ACM off and on to speed things up; that can trigger a Let's Encrypt rate limit. Fix the cause, then run:
heroku certs:auto:refresh -a example-app
Heroku documents these failure reasons:
- CN exceeding 64 character limit: the domain name is longer than 64 characters.
- Incorrect DNS settings: the record is wrong, the domain fails DNSSEC validation, or a Private Space app has no running web dyno.
- Unable to resolve DNS for domain: the name has not propagated; ACM checks Google Public DNS (8.8.8.8).
- CDN not returning HTTP challenge: the domain points at a CDN such as CloudFront that returns 404 for the challenge file.
- DNS redirect not forwarding path: the DNS provider's forwarding drops the challenge path.
- Incorrect CNAME target: the CNAME points at
<app-name>-<random-identifier>.herokuapp.cominstead of the DNS target. - Rate limited: too many certificate requests for the domains in 7 days; wait, then refresh. See Let's Encrypt rate limits.
- DNS provider timed out: refresh to retry.
- Strict TLS in CDN not supported: Cloudflare is in front but misconfigured; Heroku recommends not combining ACM with Cloudflare and disabling ACM there.
- DNS provider doesn't support CAA and CAA record prevents issuance, CAA record does not match issuer: see Step 3 and CAA record prevents issuance.
- Domain record does not exist: Let's Encrypt got NXDOMAIN; check the spelling and the CNAME.
- Domain considered unsafe: Google Safe Browsing flags the domain.
- Let's Encrypt domain blocklist: ask on the Let's Encrypt community forum.
FAQ
Does Heroku ACM cost extra?
No. Heroku's documentation says all applications include ACM for free. It uses Let's Encrypt certificates and renews them one month before they expire.
Why can't I use an A record for my root domain on Heroku?
Heroku uses dynamic IP addresses, so an A record pointing at a fixed IP will break. Use an ALIAS, ANAME or flattened CNAME record that points the root domain at the herokudns.com DNS target shown by heroku domains.
Does ACM issue wildcard certificates?
Heroku's ACM article tells Private Space apps to upload their own wildcard certificate and says Cedar-generation Private Space apps using ACM cannot have wildcard domains, while a newer generation can. For wildcard HTTPS in other cases, plan to upload your own wildcard certificate, which turns ACM off for that app.
Should I turn ACM off and on again to fix a stuck certificate?
No. Heroku warns that toggling ACM can hit a Let's Encrypt rate limit, which Heroku support cannot bypass. Fix DNS, then run heroku certs:auto:refresh.