The whole issue of expiration in cryptographic systems is extremely fraught. My gut sense is that X.509 certificate expiry is the most common cause of mega-outages these days, where by "mega outage" I mean the sort of thing that takes down entire cellphone networks or major online services for hours at a time. In the past I've tried arguing against this practice of immediately cutting all communication because a deadline expired, but cryptography as a field is highly resistant to business requirements analysis of any kind. No CEO in their right mind would ever agree to having expiry in their infrastructure but the decisions are made by people far away, very deep down in organizational stacks, and it honestly doesn't occur to most business-side people that anyone could be crazy enough to litter miniature time bombs all throughout mission critical HA infrastructure anyway.

Part of the issue is misalignment of requirements. Keys don't actually expire, of course. In the old RSA days there was a notion of a sort of slow rusting as factoring attacks tended to get better over time, so every so often you'd want to bump the size of an RSA key to keep it secure. But that wasn't something that had to be done on a deadline. When elliptic curve cryptography went off-patent and started getting deployed it fixed that, and a secp256r1 key made today is as good as one made 15 years ago.

So what is the purpose of expiry, then, in today's world?

For DNSSEC, it seems to be a kind of encoding of an assumption that keys can leak without anyone being aware of it, whilst the holes being used to do so get sort of ambiently patched anyway again without anyone being aware that they've done so. If you assume a world where keys are constantly being stolen and abused, then regular rotation can help. However, that's not the real world! These keys are stored in HSMs. Has there ever been a leaked DNSSEC key spotted being abused in the wild? Certainly it's questionable whether the juice is worth the squeeze given the outages it causes, and the way these undermine the entire system.

For certificates there's that, but the original justification was actually about constraining the size of CRLs. If certificates don't expire then in theory any decommd cert has to be recorded and stuck on a revocation list forever, which would mean they can never shrink. How exactly to handle phaseout of old keys and certificate details has experienced a lot of churn over the years with CRLs, OCSP, OCSP Stapling and nowadays CRLsets all doing similar tasks.

Still, this is primarily a logistics and cost management issue rather than an actual security problem. The task could also be done with gradual phase out in which at first expired certs only trigger warnings to developers via the browser console, Google Search console etc. Then later it graduates to a warning in the URL bar. Then eventually TLS stacks start increasing the latency on connections, etc. Then once artificial latency passes a certain threshold that's basically equivalent to an outage anyway and you may as well just return an error immediately.

Lately there's another reason for expiry, with short expiry times being enforced by the CA/B Forum so they can change the rules for certificates quicker, not keys. It took a long time to phase out SHA1 and introduce CT, the people who set the certificate rules didn't like that as their job is security, so by making certs constantly expire they hope to push people into setting up automated renewal pipelines which in turn means they can then do things like mandate new algorithms, change the contents of certificates and so on. Constant expiry certainly helps them do their job, but it makes everyone else's job harder as automated renewal isn't always easy especially outside the context of simple web servers that use LetsEncrypt.

Summary: If tomorrow I was temporarily made King Of The Internet and told that my only mission in life was to increase availability, I'd start by altering X.509 libraries to implement gradual degradation instead of hard expiry, e.g. with a sleep(time_since_expiry) call somewhere in the stack. I'd also default to simply ignoring expiration outside of TLS context, because X.509 gets used in a lot of places that aren't TLS and they're often hard to reach and fix e.g. certs that are hard-coded into embedded devices. You do NOT want your electricity grid to have an outage caused by certificate expiry. In those contexts it hardly matters because the PKIs are often custom and not very large, so CRL sizes just don't matter. You can easily list every revoked certificate for the entire lifetime of the system, if you even need PKIX revocation support at all, and for those use cases expiry is probably a much bigger business risk than attacks using obsolete algorithms.