Let’s Encrypt no longer emails you when a certificate is about to expire. It announced the change on January 22, 2025 and switched the emails off on June 4, 2025, the same day it confirmed on its community forum that “Let’s Encrypt has discontinued all expiration notification emails effective today.” Three weeks later it deleted the email addresses it had stored alongside issuance records.

Your certificates still renew exactly as before. What is gone is the warning you got when renewal had quietly stopped working.

Why Let’s Encrypt stopped

The announcement gives four reasons:

  • Automation is the norm. In Let’s Encrypt’s words, “more and more of our subscribers have been able to put reliable automation into place for certificate renewal.”
  • Privacy. Sending the emails meant keeping “millions of email addresses connected to issuance records”, which Let’s Encrypt wanted to stop doing.
  • Cost. The service “costs Let’s Encrypt tens of thousands of dollars per year”, money a nonprofit CA would rather spend elsewhere.
  • Complexity. It “adds complexity to our infrastructure”.

Since June 2025, if you give an email address to Let’s Encrypt through the ACME API, it is not stored with your account. It goes to the general ISRG mailing list system, unconnected to any account data, and the API response no longer echoes contact information back.

Were you relying on it?

Probably, if any of these is true:

  • You registered your ACME client with an email address (for example with Certbot’s --email option) and never set up any other monitoring.
  • You remember receiving an expiry warning from Let’s Encrypt at least once. Each one meant a certificate was close to expiry without a renewal: usually a renewal that had failed, sometimes a certificate nobody needed any more.
  • Some of your certificates are renewed by systems you don’t look at often: a NAS, a home server, a client’s VPS, a staging box.

The emails were never part of renewal. They were a backstop for the cases where renewal breaks without anyone noticing, and those cases have not gone away:

  • A server migration that left the renewal timer or cron job behind.
  • Port 80 closed by a firewall change, so HTTP validation fails.
  • An expired or rotated DNS API token, so DNS validation fails.
  • A renewal that succeeded while the web server kept serving the old certificate, because nothing reloaded it.
  • A hostname that moved to another server, whose certificate nobody set up.

The last two matter most, because the certificate files on disk look fine. Only a check against the live site shows the problem.

What to use instead

There are two kinds of replacement, and they catch different failures. Ideally, use one of each.

  • External expiry monitoring: a service checks the certificate your site actually serves. It catches every failure that ends with an old certificate being served, whatever the cause, but you hear about it when the remaining time drops, not on the day renewal fails.
  • Alerts from the renewal job itself: you hear on the day a renewal fails. They miss a renewal that succeeds but is never deployed or reloaded, and hosts the job doesn’t know about.

External monitoring services

Let’s Encrypt recommends Red Sift Certificates Lite (formerly Hardenize), which “is free of charge for up to 250 certificates”. Its monitoring options page lists more: Red Sift Certificates, UptimeRobot, Datadog SSL Monitoring, TrackSSL, Host-Tracker, HeyOnCall, CertKit, CertObserver and Chill SSL. They differ in price, check frequency, alert channels and how many hosts the free tier covers, so compare on those.

Expiry Watch is ours, and it is one more option of this kind. Today it monitors up to 3 domains for free: it checks once a day, emails at 30, 14, 7, 3 and 1 day before expiry, and also tracks when each domain’s registration expires. A check that fails (the site is down, the TLS handshake breaks) is reported as a failed check, never as an expiry. If you have more than three domains, one of the services above may suit you better today; paid plans for more domains are planned, not available yet.

Whatever you pick, look for:

  • Checks of the live endpoint, not just Certificate Transparency logs or the CA account. You want to know what visitors get.
  • Alerts that leave time to act. If your certificates renew with 30 days left, an alert at 14 or 7 days means something is wrong.
  • Failures reported as failures. A host that can’t be reached is a different problem from an expiring certificate, and you want to know which one you have.
  • A shared inbox or channel, not one person’s mailbox. The person who set up the certificate may not be around when it expires.

Alerts from the renewal job

Make the renewal job loud when it fails. How depends on where it runs:

  • cron: set MAILTO=ops@example.com at the top of the crontab so any output from a failing job is emailed, and make sure the job prints only on failure.
  • systemd timers: add OnFailure= to the service unit, pointing at a unit that sends a notification.
  • Kubernetes cert-manager, Caddy, Traefik and other built-in ACME clients: route their error logs or metrics into the alerting you already have.

A small do-it-yourself check

If you want something running today with no new account, this script checks a list of hosts with OpenSSL and prints a line only for certificates expiring within 14 days, or hosts that can’t be checked. Run it daily from cron with MAILTO set, and silence means everything is fine.

#!/usr/bin/env bash
# expiry-alert.sh: prints a line for each host whose certificate expires within
# DAYS days, or that can't be checked. Prints nothing when everything is fine.
DAYS=${DAYS:-14}
while IFS= read -r host || [ -n "$host" ]; do
  [ -z "$host" ] && continue
  cert=$(openssl s_client -connect "$host:443" -servername "$host" </dev/null 2>/dev/null)
  if ! printf '%s' "$cert" | openssl x509 -noout >/dev/null 2>&1; then
    echo "$host: check failed (no certificate received)"
  elif ! printf '%s' "$cert" | openssl x509 -noout -checkend $((DAYS * 86400)) >/dev/null; then
    echo "$host: expired or expires within $DAYS days ($(printf '%s' "$cert" | openssl x509 -noout -enddate))"
  fi
done < "${1:-hosts.txt}"

Run on October 14, 2026 against example.com, expired.badssl.com (a test site whose certificate expired in 2015) and no-such-host.invalid (a name that can’t exist), it printed two lines and stayed quiet about example.com:

expired.badssl.com: expired or expires within 14 days (notAfter=Apr 12 23:59:59 2015 GMT)
no-such-host.invalid: check failed (no certificate received)

The script separates “no certificate received” from “expiring” on purpose: openssl x509 -checkend exits with the same code for both, so testing it alone would report an unreachable host as an expiring one. For a fuller version with days remaining, timeouts and a summary table, see how to check an SSL certificate’s expiry date.

Other Let’s Encrypt changes worth knowing

The same few years brought other changes that affect anyone who runs Let’s Encrypt certificates:

  • OCSP is gone. Let’s Encrypt turned off its OCSP responders on August 6, 2025, after dropping OCSP URLs from new certificates in May 2025.
  • No more client authentication by default. Since February 11, 2026 the default profile no longer includes the TLS Client Authentication extended key usage; the opt-in tlsclient profile was available until July 8, 2026 (details).
  • Shorter certificates. The default lifetime drops from 90 to 64 days on February 10, 2027, and to 45 days on February 16, 2028. The whole industry follows by 2029. See 47-day SSL certificates: timeline and prep.

Shorter lifetimes make the missing emails matter more: with a 45-day certificate, a renewal that silently stops leaves you about two weeks, not a month.

Sources

All sources were checked on October 14, 2026.