What Happens When an SSL Certificate Expires?
What happens when an SSL certificate expired: browser warnings, broken APIs, lost trust and how fast the failure cascades — plus what to do about it.
The moment an SSL certificate expired on a public endpoint, the failure is total and immediate — there is no grace period, no degraded mode, no warning shown only to admins. The instant the clock passes the certificate's notAfter date, every client that validates certificates properly refuses the connection. Browsers throw a full-page interstitial, APIs raise TLS errors, mobile apps fail to sync, and your monitoring (if it checks the chain) starts screaming. This post walks through exactly what breaks, in what order, and why it cascades faster than most teams expect.
The browser experience: a wall, not a warning
For a human visiting your site in Chrome, Firefox, Safari or Edge, an expired certificate produces a full-screen error page — NET::ERR_CERT_DATE_INVALID in Chrome, SEC_ERROR_EXPIRED_CERTIFICATE in Firefox. Crucially:
- It is not a dismissible banner. The page content is hidden behind the warning.
- Getting past it requires clicking "Advanced" and then an explicit "proceed anyway" link — something most users have (rightly) been trained never to do.
- On sites using HSTS (HTTP Strict Transport Security), there is no proceed option at all. The browser hard-refuses. If you've ever set
Strict-Transport-Securitywith a longmax-age, an expired cert means a genuinely unreachable site for returning visitors.
For a commercial site, this is indistinguishable from being completely offline. Conversion goes to zero, and the brand damage of a scary red security warning lingers after you've fixed it.
The machine experience: silent, cascading failures
Humans at least see the error. Machine-to-machine traffic often fails in ways that are far harder to diagnose, because the symptoms surface somewhere else entirely:
- API clients reject the TLS handshake. Depending on the language and library, you'll see
CERTIFICATE_VERIFY_FAILED(Python),x509: certificate has expired(Go),PKIX path validation failed(Java), or a genericSSL_ERROR. - Webhooks stop being delivered. Payment providers, CI systems and SaaS integrations calling your endpoint quietly back off and retry, then give up. You don't get an error — you get an absence of events.
- Mobile apps fail to reach their backend. Users see spinners and "couldn't connect" toasts, and they blame the app, not your cert.
- Internal service meshes break. One expired cert on a service everyone depends on can take down a surprising fraction of an internal estate.
The dangerous part is the blast radius mismatch: a single expired certificate on an auth service or an API gateway fails every downstream consumer at once. The incident channel fills with reports that look unrelated until someone runs openssl against the right host.
How fast does it cascade?
Faster than your on-call can triage, typically:
| Time after expiry | What's happening |
|---|---|
| T+0 seconds | Every new TLS handshake to the endpoint fails. Existing long-lived connections may survive briefly, masking the problem. |
| T+1–5 minutes | Health checks, synthetic monitors and webhook senders start failing. Retry storms begin. |
| T+5–15 minutes | Customer reports and internal alerts converge. Dependent services exhaust retries and surface their own errors. |
| T+15 minutes onward | Triage time is dominated by finding the expired cert among the noise, not fixing it. |
The fix itself — renew and deploy — is usually quick once you know the cause. The expensive part is the detection-and-attribution gap. That gap is exactly what proactive expiry monitoring removes.
Why "it renews automatically" is not a defence
Plenty of teams that suffered an expired-cert outage had automation. Renewal jobs break silently: a cron entry lost in a rebuild, a port-80 redirect that broke the HTTP-01 challenge, an expired API token behind a DNS-01 challenge, or a cert that renewed on disk but was never reloaded into the running server. Automation lowers how often this happens; it does nothing for the cases where it fails, because a renewal system reporting on itself is the least trustworthy possible monitor. (We dug into the renewal failure modes in Let's Encrypt renewal failures.)
What to actually do
- Check what's served, from outside. The only number that matters is the
notAfteron the certificate the live endpoint presents to clients right now — not what's in your config or renewal log. - Alert on a tiered schedule, well before expiry — 30, 14, 7 and 1 days — so a single snoozed notice isn't your only warning.
- Verify after remediation. Confirm the served certificate actually changed; "marked the ticket done" is not the same as "the new cert is live".
- Inventory the long tail. The cert that bites you is usually the one outside your main automation: an appliance, an internal CA, a forgotten staging subdomain. Add every endpoint, not just the obvious ones — see setting up endpoint checks.
DomainOps watches the certificate each of your HTTPS endpoints actually serves and sends tiered alerts to email, Slack or Pushover days before anything expires — so the first person to learn about an expiring cert is you, not your customers. Start monitoring your endpoints in a few minutes.