Blog / Let's Encrypt Renewal Failures — When 90-Day Automation Silently Stops
ssl lets-encrypt certificate-monitoring automation

Let's Encrypt Renewal Failures — When 90-Day Automation Silently Stops

Let's Encrypt automation fails quietly — broken certbot upgrades, rate limits, blocked port 80, lost cron jobs. Independent expiry monitoring is the net.
The CompleteStatus Team · · 6 min read
Let's Encrypt Renewal Failures — When 90-Day Automation Silently Stops
Want this checked continuously?
CompleteStatus grades your headers, SSL and email security 24/7 — free, commercial use allowed.
Monitor your site free

Let's Encrypt changed the economics of HTTPS — free certificates, issued in seconds, now securing well over a hundred million sites. The design bet behind its 90-day certificate lifetime is that renewal will be automated, and when the automation works, it's genuinely magical: certificates renew themselves forever and you never think about expiry again.

The catch is in the word when. Ninety-day certificates mean your renewal machinery must succeed, unattended, at least every couple of months — and it fails in ways that produce no error you'll see. The certificate stays valid for weeks after the automation dies, so everything looks fine right up until a Saturday morning when every browser greets your customers with a full-page security warning. Here are the failure modes we see over and over, and the safety net that catches all of them.

The ways renewal automation actually dies

  • The ACME client broke during a system upgrade. The classic. An OS upgrade moves Python, a package manager half-removes certbot, or a distro package falls behind — certbot itself has been migrating distributions toward snap-based installs lately, and more than one server has ended up with the old apt version and the new snap version fighting over the same config directory. Every renewal attempt since the upgrade has failed; nobody was watching the output.

  • Port 80 got firewalled. The HTTP-01 challenge — the most common validation method — requires Let's Encrypt to reach http://yourdomain/.well-known/acme-challenge/ on port 80. Then a well-meaning security pass "closes unnecessary ports," or a new CDN/load balancer stops forwarding plain HTTP to the origin. HTTPS keeps working (port 443 is open, the current cert is valid), so nothing looks wrong — but validation now fails every time it's attempted.

  • DNS-01 misconfiguration. Wildcard certificates require the DNS-01 challenge: the client must create a _acme-challenge TXT record via your DNS provider's API. An expired API token, a migrated DNS provider, or a CNAME pointing at a delegation zone that no longer exists — and renewal fails. DNS-01 has the most moving parts, and every part is a credential or a record that can silently rot.

  • The renewal cron never made it to the new server. You migrated hosts, copied the web root and the certificates, restored the vhost configs — and the certbot timer or cron entry stayed behind on the old box. The copied certificate is valid for up to 90 more days, which is exactly long enough to forget the migration ever happened.

  • Rate limits, at the worst moment. Let's Encrypt's production limits include 50 certificates per registered domain per week and 5 duplicate certificates per week. You'll basically never hit these in normal operation — you hit them while debugging in a panic, re-issuing the same cert until the limiter locks you out for days. (Rehearse against the staging endpoint — --dry-run — which has generous separate limits.)

  • Renewal succeeded; the reload didn't. The sneakiest one: a fresh certificate lands on disk, but the web server never reloads, so it keeps serving the old one from memory until the day that old cert expires. A missing --deploy-hook is the usual culprit:

# Test the whole pipeline, including hooks, against staging:
certbot renew --dry-run

# The reload must be wired to renewal, not to hope:
certbot renew --deploy-hook "systemctl reload nginx"

Note the common thread — in every case the failure is quiet, and the existing certificate keeps working for weeks afterward. The gap between "automation died" and "site broke" is precisely what makes this class of outage so common.

Check what you're actually serving — from outside

The ground truth isn't what's on disk; it's what your server hands to a browser. Ask it directly:

echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null \
  | openssl x509 -noout -dates -issuer

If notAfter is further out than about 30 days ago plus 90, your renewal ran recently; certbot renews at the 30-days-left mark by default, so a correctly functioning setup should rarely show fewer than ~30 days remaining. A cert showing 12 days left means your automation has already been dead for weeks — you just found out early. Check every hostname (the -servername flag matters for SNI) and don't forget the non-web listeners — mail servers, admin panels — that certbot's hooks often don't reload.

Mark your calendar: September 30, 2021

A heads-up specific to this year: DST Root CA X3, the root certificate Let's Encrypt has cross-signed from since the beginning, expires on September 30, 2021. Modern browsers and operating systems already trust Let's Encrypt's own ISRG Root X1 root, so mainstream visitors should be unaffected — but old clients that only trust the expiring root (older Android versions are the big population, plus aging embedded devices and outdated OSes) may start rejecting Let's Encrypt certificates after that date.

What to do between now and then: keep your ACME client current (chain-handling behavior around the transition is exactly the kind of thing updates address), check whether your traffic includes meaningful numbers of very old clients, and if you run API clients or servers that call Let's Encrypt-secured services, make sure their trust stores include ISRG Root X1. It's in the future, it's on a known date, and it will still surprise thousands of teams — don't be one of them.

Independent expiry monitoring: the net under the trapeze

Everything above shares one property: the renewal system cannot be trusted to report its own death. Certbot logs to a file nobody reads; a dead cron makes no sound at all. The fix is structural — a check that lives outside the machinery it watches:

  • Independent. Runs from the outside, shares nothing with your server, can't die in the same upgrade.
  • Continuous. Connects to your real endpoints and reads the actual certificate being served — catching not just expiry but the renewed-but-never-reloaded case.
  • Early and tiered. With certbot renewing at 30 days out, an alert at 25 days remaining means "automation has been failing for days" — a calm, fix-it-this-week signal rather than a weekend emergency. Escalate harder at 14 and 7.

The renewal automation is the trapeze act; monitoring is the net. You want both, built by different people.

Ninety days is a feature — with a net

Short-lived certificates are genuinely better security, and the discipline they force — real automation instead of a calendar reminder and a prayer — is good for you. The only unacceptable state is automation presumed working with nothing watching it.

CompleteStatus checks the certificate your servers actually serve and alerts well before expiry — email, Slack, Discord, Telegram or webhook — alongside uptime and status-code-aware HTTP checks in one place. Create a free account, add your domains, and let the robot confirm every 90-day cycle — including the one that runs the week of September 30.

Stop checking by hand

CompleteStatus runs these exact checks around the clock — uptime, SSL, DNS, security headers and SPF/DKIM/DMARC — and alerts you the moment something changes. One dashboard, one bill.
Start free Run a free check
Uptime is table stakes. We watch the rest — security headers, email authentication, certs and DNS, with the fix attached.
Start free
Company
© 2026 CompleteStatus. All rights reserved. CompleteStatus — operated in the United States · support@completestatus.com