Skip to main content

SSL Certificate Renewed but Still Showing Expired: Find the Stale Copy

SSL certificate renewed but still showing expired? The new certificate exists; something is serving the old one. Find which layer it is and stop a repeat.

FLAREWARDEN
FlareWarden Team
7 min read

The renewal worked, and the new certificate is sitting on disk with a date a few months out. Visitors still get “Your connection is not private”, because somewhere between your server and their browser a layer is still handing out the old certificate. Your job isn’t to renew again; it’s to find which layer that is.

First, Look at What Is Actually Served

Don’t trust the browser and don’t trust the file. Ask the live endpoint which certificate it presents:

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

The notAfter line is the certificate real clients receive. The -servername flag matters: it sends the hostname the way a browser does, so a server hosting several sites hands you the right certificate instead of its default one.

That one command splits the problem in two:

  • It shows the new date. The server is fine and the stale copy is local to you. Skip to the last cause below.
  • It shows the old date. Something on the path is serving the old certificate. Work through the list in order.

Run it from a second network too, a phone hotspot or a remote server. If two vantage points disagree, you’ve already learned you’re dealing with more than one server or a CDN.

Why an SSL Certificate Renewed but Still Showing Expired Happens

These are ordered by how often they’re the answer and how fast you can rule each one out.

The Web Server Never Reloaded

nginx and Apache load certificates along with their configuration. nginx’s own guide is explicit that changes are not applied until you reload or restart, and Apache’s graceful restart is the signal that makes the parent process re-read its configuration files. Renewing a certificate writes a new file. Until the process reads it again, the old certificate stays in memory and keeps being served.

sudo nginx -t && sudo nginx -s reload
sudo apachectl configtest && sudo apachectl -k graceful

If Certbot did the renewal, fix this permanently with a deploy hook. Certbot runs --deploy-hook commands only after a successful renewal, and any executable in /etc/letsencrypt/renewal-hooks/deploy runs the same way. A two-line script there that reloads your web server is the difference between renewal and renewal that takes effect.

This cause keeps getting more common. Let’s Encrypt certificates are valid for 90 days by default, with six-day certificates available as an opt-in, so a manual reload step now has to happen several times a year instead of once.

You Renewed One Server Out of Several

Behind a load balancer, each backend presents its own certificate unless TLS ends at the balancer. Renew and reload three nodes out of four and one visitor in four still sees the expired one. This is also why the problem can look intermittent: refresh and it’s fine, refresh again and it’s back.

Test each backend directly by pointing openssl s_client -connect at the node’s own IP while keeping -servername set to the public hostname. Any node that answers with the old date is your culprit.

A CDN or Proxy Presents Its Own Certificate

With a CDN in front, there are two certificates involved in a single request. Cloudflare’s documentation describes this directly: an edge certificate the CDN presents to visitors and a separate origin certificate between the CDN and your server. Renewing the certificate on your server does nothing for a visitor who sees the edge certificate, and the reverse is true too.

Check which one your openssl output shows. If the issuer is your CDN’s certificate authority rather than the one you renewed with, the expired certificate lives in the CDN’s settings, not on your server.

The New Certificate Was Installed but Not Bound

Some hosting panels and cloud platforms keep certificates in a store and attach them to a domain as a separate step. Uploading the renewed certificate doesn’t switch the binding. Azure App Service’s certificate binding guide, for example, lays out renewing an IP-based binding as three steps: upload the new certificate, bind it to the domain, then delete the old one. Skip the middle step on any platform that works this way and the old binding keeps serving the old certificate.

DNS Still Points at the Old Server

After a hosting move, the renewal happens on the new server while some resolvers still send visitors to the old one, which carries the old certificate and no longer renews it. Compare dig +short example.com against the IP of the server you actually renewed. We’ve written about how DNS failures hide in plain sight; this is one of the quieter versions.

It’s Only Your Machine

If openssl from another network shows the new date, the stale certificate is local. Close the browser completely, try a private window or another device, and check whether your office network inspects TLS traffic, because an inspecting proxy presents its own certificate to you and nobody else. Waiting for this to fix itself is fine, provided the check from outside is genuinely clean.

The Real Failure Is Finding Out From a Visitor

Every cause above has the same shape. The renewal succeeded, so every system that tracks the renewal reports success: your registrar dashboard shows a valid certificate, Certbot logs a successful renewal, and the file on disk is correct.

The only place the failure is visible is the connection a real client makes, which is why the report usually arrives from a customer.

That’s the gap an external check closes. In FlareWarden, every HTTPS uptime monitor tracks the certificate automatically, and it reads the certificate from the TLS handshake of the check itself, the same way a browser gets it. It doesn’t look at a file or at your certificate authority’s records.

Expiry alerts go out at 30, 14 and 7 days by default, adjustable in your preferences, plus a final notice the day before. SSL tracking is included on every plan, free included.

That design is what makes the monitor useful after a renewal. If you renewed last week and the monitor’s certificate details still show the old expiry date, or the countdown alerts keep coming, the served certificate hasn’t changed, whatever the file on disk says. The monitor has no way to be fooled by a successful renewal log.

Some honest limits apply. A single check reaches whichever backend the load balancer picks, so a stale node in a large pool can take several checks to surface. A monitor pointed at a CDN-fronted hostname sees the edge certificate, not your origin’s.

A renewed certificate that covers the monitored hostname is recorded as expected rather than sent as an alert, so confirm a renewal by seeing the new expiry date appear, not by waiting for a notification. If certificates on internal hostnames matter to you, monitor those hostnames directly too, a point we made at more length in why certificate expiry keeps catching companies out.


Key Takeaways

  • Check the served certificate, not the file. openssl s_client with -servername tells you in one command whether the problem is on the path or on your own machine.
  • Reload after every renewal. nginx and Apache keep the old certificate in memory until they re-read their configuration, so wire a Certbot deploy hook to do it.
  • Load balancers and CDNs multiply the places a certificate lives. Test each backend by IP, and check whether your output shows the CDN’s edge certificate or your origin’s.
  • Renewal success is not deployment success. Registrar dashboards and renewal logs only prove a certificate exists. An external check of the live handshake proves visitors receive it.
  • Shorter lifetimes raise the stakes. At 90 days or less per certificate, a manual reload step fails several times a year, not once.

Want to see the certificate your visitors actually receive, before they see the warning? Start monitoring free with FlareWarden — SSL expiry tracking on every HTTPS monitor, 15 monitors, no credit card required.