Guide
Heroku SSL endpoint certificate expired
Heroku apps show expired TLS on custom domains when ACM fails or legacy SSL endpoints age out. Review heroku certs output, fix DNS to Heroku targets, and confirm Automated Certificate Management is enabled.
Updated May 16, 2026 804 words
heroku ssl certificate expired on a custom domain means ACM did not replace the leaf—or traffic bypasses Heroku's SSL endpoint entirely.
Heroku Automated Certificate Management (ACM) renews Let's Encrypt certs for apps on supported dyno types when DNS CNAMEs target *.herokudns.com or stated HEROKU targets.
Legacy paid SSL addons and older sni endpoints still appear in aging runbooks; expired manual uploads break clients until removed or renewed.
Use Heroku CLI plus external openssl before scaling dynos or redeploying slug builds.
First response
heroku certs -a APPNAME
heroku domains -a APPNAME
heroku certs:auto -a APPNAME
Note domains with ACM Status: failing or manual certs near expiry. Run openssl on each custom domain from the public internet.
See curl SSL certificate expired when APIs document TLS failures.
Archive heroku domains and certs output with timestamps. Note review app versus production app ownership. Confirm billing status; some legacy stacks lack ACM entirely. Capture whether a recent pipeline promotion copied domain settings without a matching DNS change ticket.
What this error means
Heroku routers terminate TLS using certificates attached to the app's SSL endpoint. ACM failures leave the previous cert until it expires, then browsers block production URLs.
*.herokuapp.com hostnames use Heroku-managed certs separate from your custom domain ACM state.
PKIX errors during OAuth or mobile API calls indicate the hostname in those URLs—not an internal DATABASE_URL.
Heroku routers terminate TLS for custom domains using ACM-managed material. Manual uploads block automation until removed. Default herokuapp.com certificates are independent per app. Pipeline promotions can copy domain attachments faster than DNS teams update registrar records.
Common causes
DNS not CNAME'd to Heroku after migrating to another cloud.
ACM disabled on apps that still had a one-time uploaded cert.
Wildcard DNS pointing apex to non-Heroku A records.
Review apps on free legacy stacks without ACM support.
Concurrent manual cert conflicting with ACM renewal.
DNS CNAME drift during cloud migrations leaves ACM failing while dynos stay healthy. Partners testing against old manual endpoint certs see expiry even after ACM succeeds elsewhere.
Confirm from the outside
OpenSSL
echo | openssl s_client -connect HOST:443 -servername HOST 2>/dev/null | openssl x509 -noout -dates -subject -issuer
Replace HOST with the public hostname users type.
How to read the output
Issuer should be a public CA under ACM. Manual uploads show custom issuer names until removed.
curl
curl -vI --connect-timeout 10 https://HOST/ 2>&1 | grep -Ei 'expire|SSL certificate|subject:|issuer:'
Enable ACM
heroku certs:auto:enable -a APPNAME
After DNS fixes, wait for ACM status ok. Remove obsolete certs:
heroku certs:remove CERTNAME -a APPNAME
openssl every custom domain listed in heroku domains, including redirects from apex to www. Paste heroku certs output next to openssl in the ticket because ACM status columns explain failures that openssl alone cannot distinguish from simple expiry.
Fix checklist
- heroku domains:add for missing hostnames.
- Fix DNS per heroku domains output.
- Enable ACM; remove stale manual certs.
- Wait for certs:auto status OK.
- Smoke-test web and API clients on custom domains.
- Verify redirect chains from apex to www if used.
- Document which endpoints partners integrate with.
- Monitor each custom domain externally.
Roll out and verify
Heroku ACM renewal does not require slug rebuilds. Resist redeploying unless configuration variables tied to public URLs changed. Instead, watch heroku certs:auto until domains flip to ok after DNS corrections.
Legacy manual certificates should be removed once ACM is stable—dual cert states confuse operators and break automation. Document any compliance requirement that forced manual uploads; otherwise default to ACM.
Partners integrating via custom domains may cache TLS fingerprints in mobile SDKs. Notify them after intermediate CA changes even when notAfter was the primary incident driver.
If you also run load balancer SSL expiry on a corporate edge in front of Heroku, test end-to-end after both layers are green.
Remove obsolete SSL add-on endpoints after ACM succeeds. Update mobile apps storing pinned hostnames. Confirm heroku certs:auto shows ok for every custom domain in release notes so stakeholders know which URLs were validated.
Executive dashboards tracking only herokuapp.com health should add custom-domain synthetics because that is what customers bookmark. Heroku Private Space and Shield configurations still terminate customer TLS on platform routers for standard custom domains—runbooks should not assume private networking bypasses ACM. Review apps may inherit custom domain configs from pipeline promotions; confirm production DNS still matches the production app after promotions. Dyno restarts do not refresh ACM state; avoid noisy redeploys during SSL incidents. Salesforce integrations and Heroku Connect jobs calling HTTPS endpoints may log generic HTTP failures—correlate timestamps with ACM status transitions. For apps with legacy SSL endpoint add-ons, budget time to validate clients pinned to old intermediate chains after migrating to ACM-only stacks. Scheduled rake tasks hitting vanity URLs fail overnight jobs silently; grep logs for SSL errors before blaming application code. Partner APIs documented with example curl commands should be re-run from CI after ACM status returns to ok. Compliance scans that whitelist herokuapp.com but not custom domains produce passing audits while shoppers fail. Document dyno types not eligible for ACM so product owners do not assume uniform behavior across environments. After incidents, rebuild internal runbooks that previously referenced manual openssl uploads so new engineers default to ACM workflows. Treat every custom domain in heroku domains output as a monitored production asset with the same on-call severity as database failover. OAuth providers caching discovery documents may need time to refresh after TLS recovery—plan retests for login spikes. Mobile deep links bundled in partner apps need manual regression because ACM fixes do not update installed clients.
Finance approvals for paid SSL addons sometimes delay ACM migrations; document when manual certificates remain intentional so incident command knows whether heroku certs remove is appropriate. Batch openssl checks immediately after registrar maintenance windows because glue record edits frequently correlate with ACM failing hours later even when dynos show green health. Paste ACM ok status into status pages when executives ask for evidence. Schedule a follow-up openssl run twenty-four hours later to catch delayed CNAME propagation. Notify API consumers when intermediate issuers change so they update trust stores if needed. Document the renewed leaf serial numbers in the closure notes.
When to use automation
Certificate files on disk and green panels lie until a stranger's TLS handshake succeeds. Schedule live checks on the exact hostname shoppers or API clients resolve, including redirects and the certificate presented after your platform edge terminates the connection. Pair TLS notAfter with RDAP domain registration data so revalidation is not blocked by registrar billing.
Run a one-shot proof on /check, then add the production hostname to monitoring with alerts at 30, 14, 7, and 1 day thresholds. ssldays reads the live chain external users see—useful when shared hosting, PaaS edges, or CMS layers each claim TLS is fine.
Frequently asked questions
herokuapp.com domain?
Separate cert state from custom domains.
DnsTarget not matching?
ACM stays failing until DNS matches CLI output.
Docker stack on Heroku?
Still uses Heroku router TLS for custom domains.
Legacy SSL add-on?
Migrate to ACM where supported before expiry surprises.
See what the server presents right now
Free live certificate check — no signup.