Guides · TLS

TLS Certificate Expiration And Troubleshooting

Most TLS outages are simply expirations nobody noticed. Here's how to inspect what's actually served, what each date means, and the common ways renewals quietly fail.

By Cody · 7 min read · Published

What's actually in a certificate

A TLS certificate carries, at minimum:

  • The subject (Common Name, mostly cosmetic now).
  • The SAN list — every hostname the cert is valid for.
  • The issuer — the CA that signed it.
  • notBefore and notAfter — the validity window.
  • The signature algorithm and serial number.

Modern browsers ignore the Common Name entirely and check the SAN list. If you renewed a cert and it "works" on the apex but not www., the SAN is the place to look.

Why short lifetimes are now the norm

Public CA certificates have steadily shrunk: 825 days a decade ago, 398 in 2020, 90 days for Let's Encrypt and most automated issuers today, with industry roadmaps moving even shorter. Short lifetimes are good for the ecosystem and bad for anyone still renewing by hand. If you are reading this, you should be on automated renewal.

Inspecting what's served vs what's installed

The certificate file on disk and the certificate the server is actually presenting are not always the same — config reloads get missed, the wrong vhost gets the renewal, an ancient load balancer caches a copy. Always inspect what is served, not what is on disk.

Use this site's TLS inspector, or from the command line:

openssl s_client -connect example.com:443 -servername example.com -showcerts < /dev/null \
  | openssl x509 -noout -subject -issuer -dates -ext subjectAltName

The -servername flag is essential — without it you may get the default cert on a shared IP, not the one for the hostname you care about.

The four common failure modes

Almost every cert outage is one of these:

  1. Expired leaf. The renewal job did not run, or it ran but did not reload the service. Browsers show a stark error page; APIs reject every request.
  2. SAN mismatch. The hostname changed (added www., added a region subdomain) and the cert was reissued for the old set. Chrome showsNET::ERR_CERT_COMMON_NAME_INVALID.
  3. Missing or wrong intermediate. Server presents only the leaf; clients that do not chase AIA fail. Chrome may "work" while curl and Java break.
  4. Wrong cert on the SNI host. Multiple hostnames share one IP, the new cert is bound to the wrong vhost. Symptom: the right cert appears for one host and a default cert appears for the other.

ACME / Let's Encrypt renewal pitfalls

The recurring causes when Let's Encrypt renewals quietly fail:

  • Port 80 is firewalled and the HTTP-01 challenge cannot reach the server. Either reopen 80 or move to DNS-01.
  • The DNS provider does not allow API-driven TXT updates, so DNS-01 cannot finish. Plan for this when picking a registrar.
  • Rate-limit lockouts after too many failed attempts. The cert renews fine, then the automation hits a 5-per-week wall and stops trying. Fix the underlying error rather than increasing retries.
  • Cert renewed but service not reloaded. The deploy hook is the most-skipped piece of automation. Always include it.

Monitoring that actually catches problems

Effective TLS monitoring has four properties:

  • Alerts at 30 days and 7 days remaining.
  • Covers every public hostname, not just one canonical name.
  • Validates the full chain, not just the leaf expiry.
  • Watches Certificate Transparency logs for unexpected issuance against your domains.

CT-log monitoring is the cheapest insurance against a misissued or rogue certificate going unnoticed. Several free services email when a new cert appears for a watched domain.

What to do when it's already expired

The recovery path:

  1. Reissue immediately — manual ACME run if automation is broken.
  2. Deploy and reload the service. Confirm the process is reading the new file.
  3. Verify with /tools/tls against the public hostname (not localhost, not the load-balancer IP).
  4. After the immediate fix, find the cause of the renewal failure and fix it. Outages repeat.

Inspecting a healthy certificate

Example input
example.com:443
Example result
Subject:       CN=example.com
SANs:          example.com, www.example.com
Issuer:        DigiCert TLS RSA SHA256 2020 CA1
notBefore:     2026-03-28T00:00:00Z
notAfter:      2026-06-15T23:59:59Z
Days remaining: 39
Chain:         leaf -> DigiCert TLS RSA SHA256 2020 CA1 -> DigiCert Global Root CA (trusted)

39 days remaining is healthy under a 90-day cert. Anything under 30 should already be alerting; anything under 7 should be paging.

Related tools

FAQ

How early should renewal alerts fire?

Two thresholds are enough: 30 days out for human attention, 7 days out for an emergency page. The 30-day window catches normal automation glitches; the 7-day window forces escalation if nothing else has worked.

Why does Chrome trust my cert but curl doesn't?

Chrome implements AIA fetching and will pull a missing intermediate certificate from the URL embedded in the leaf. Most command-line tools and many libraries do not. If your server is missing the intermediate, Chrome papers over it but curl, Java, and Go fail. Always serve the full chain.

Can a certificate be valid but still rejected?

Yes. A SAN mismatch, an untrusted root, a revoked cert with OCSP/CRL checking on, a failure in CT log requirements, and a CAA record that contradicts the issuer all cause rejection of an otherwise dates-valid certificate.

What's the difference between a certificate expiring and a CA expiring?

Your leaf cert expires every 90 days or so under modern CAs. The intermediate that signs your leaf has its own expiry, typically several years out. The root expiry is decades out. Cross-signed roots — common in transitions — can have surprising expiries that affect older clients.

Do I need to restart the server after renewal?

Usually a graceful reload is enough; nginx, Apache, and HAProxy all read the cert at process start without breaking active connections. Some load balancers and TLS-terminating proxies require an explicit reload signal — check the runbook for yours and bake the reload into the renewal script.

Last reviewed: 2026-05-06.