The leaf cert was fine. The intermediate expired and took the site down anyway.

You built the cert monitoring, and it is good. It pages on not_after, watches every public hostname, and has caught real renewals before they lapsed. But one assumption baked into it eventually bites: that a valid leaf means a valid connection. The leaf is the only object you inventory, so the leaf is the only thing your alerting can see expire.

Clients do not validate a leaf. They validate a path, and that path contains certificates you never put on a dashboard.

How chain validation actually fails clients

A handshake succeeds only when the client can build a chain from your leaf up to a root it already trusts, with every link inside its validity window and none revoked. Your server presents the leaf plus whatever intermediates you stapled into the bundle. The client brings the root from its own store. If an intermediate in the presented bundle is past not_after, the leaf's dates stop mattering. So does the leaf's date for any cross-signed CA cert the client is forced to consider while building the path.

That is why "the cert is valid until November" is half a sentence. Valid where, for which client, along which path? A 90-day leaf renews itself out of trouble. A ten-year intermediate sits in the bundle until the day it doesn't, then drops every leaf underneath it at once.

The root-expiry events everyone remembers

The textbook case is Let's Encrypt's DST Root CA X3, which expired on 2021-09-30. Leaf certs issued that week were fine. The breakage came from the cross-sign: Let's Encrypt chained ISRG Root X1 through the older DST root so it would still validate on ancient Android devices. Clients that had ISRG Root X1 directly in their trust store had a clean, non-expired path sitting right there. Plenty of them did not take it.

OpenSSL 1.0.2 preferred the longer untrusted chain it was handed, walked it up to the expired DST root, and returned a verification failure instead of stopping at the valid root it already trusted. The leaf was current. The path the client chose dead-ended at an expired cross-sign. Sites went dark on the older clients least likely to get a fast OS patch. AddTrust's external root expiry in 2020 broke the same way, for the same structural reason.

Why leaf-only monitoring hands you false confidence

Leaf-only alerting is not a little incomplete. It is blind to a whole failure class, and it reports green while you walk into it. Three reasons it keeps catching teams out:

Inventory and alert on every cert in the path

Treat the served chain as the unit of inventory. For every hostname, record the full bundle the server presents and the not_after of each link, then alert on the earliest expiry in the path rather than the leaf's. Re-fetch the chain on a schedule, because CAs change their default bundles and a routine renewal can quietly swap your intermediate. Validate against more than one trust store and at least one older path-building stack, so a cross-sign trap surfaces in staging instead of an incident.

This is the visibility Automate Certificates builds per environment: every cert in the served path gets inventoried with its own clock, and alerts fire on the first link to expire rather than the last one you happened to be watching. To see your real chains, expiries and all, start by mapping what your endpoints actually serve on the features page.