Abstract

In July 2024, DigiCert discovered they’d been issuing certificates with improper domain validation for five years. They gave customers 24 hours to replace 83,000 certificates. CISA issued an emergency alert. Critical infrastructure operators couldn’t meet the deadline. Some customers sued.

That’s what mass revocation looks like in practice. The CA finds a compliance problem, the clock starts, and everyone scrambles.

ACME Renewal Information (ARI) is the fix. It’s a protocol extension that lets a CA talk directly to your ACME client and say: renew this certificate early. Published as RFC 9773 in September 2025, it came out of Let’s Encrypt’s own experience revoking 3 million certificates in 2020 with no mechanism to coordinate replacements.

How ARI works

ARI adds a renewalInfo endpoint to the ACME server. Your client polls it for each certificate and gets back a suggestedWindow: a start and end timestamp telling the client when to renew the certificate. Under normal circumstances this is just a narrow window somewhere near the end of the certificate’s lifetime. Nothing unusual happens.

When ordering the certificate renewal, the client provides a replaces field. This lets the CA revoke the predecessor immediately rather than waiting for it to expire naturally, and it exempts the renewal from rate limits. This leaves fewer stale certificates floating around for BygoneSSL.

If there is a problem at the CA and they need to revoke certificates, they can set the renewal window to the past. The client polls, sees a window already elapsed, and renews immediately. No email. No manual intervention. The client just does the right thing.

The response also includes a Retry-After header. This is the CA telling the client how often to check back. Let’s Encrypt currently returns 21600, which is 6 hours. The RFC says clients MUST re-poll after this interval. That word is not an accident.

The protocol worked. The adoption didn’t.

In September 2024, Let’s Encrypt discovered a compliance issue with 133,613 unexpired certificates. They had 5 days to revoke them all. They set the ARI suggestedWindow to the past for every affected certificate, telling any listening client to renew immediately.

About 7,500 certificates were renewed via ARI. That’s only 5.6% of the affected pool.

The protocol did exactly what it was supposed to do. The problem is that 94% of clients weren’t listening.

Cron-based clients have an architecture problem

Certbot and acme.sh are two of the most popular ACME clients. Both run as scheduled jobs. That’s the problem.

Certbot added ARI support in version 4.1.0. But it checks ARI only when certbot renew happens to run. There’s no background loop to check in between runs. Most default packages run every 12 hours. The documentation says weekly is fine.

It’s not fine.

Let’s encrypt says Retry-After: 21600. That’s 6 hours. Run it weekly and you could miss your window to replace certificates without an outage.

Certbot also doesn’t send the replaces field. When your client renews a revoked certificate, it’s supposed to tell the CA which cert it’s replacing so the CA can close the loop immediately and waive rate limits. Certbot skips this. Partial ARI compliance is better than nothing, but it’s still partial.

acme.sh doesn’t try. No ARI support at all. Feature request #4944 has been open since January 2024. During a mass revocation event, acme.sh users wait for an email and run --renew --force manually.

Manually is the enemy now.

What real ARI compliance requires

The RFC’s recommended algorithm is straightforward, but it assumes a client that’s always running. Poll the renewalInfo endpoint. Get the window. If that time is in the past, renew immediately. Otherwise, sleep until the Retry-After interval and check again.

That loop only works if the client actually loops. A cron job that fires twice a day isn’t a loop. It’s a check-in. If the CA needs a response within 6 hours and your client wakes up in 24, you’re very late.

CertKit is always on. We’re the ACME client for every certificate in your account, running as a service, not a scheduled task. Our ARI implementation calls Let’s Encrypt’s renewalInfo endpoint exactly when they tell us to. When a certificate’s window changes, we renew the certificate automatically and deploy it where its supposed to go. We include the replaces field on every renewal so Let’s Encrypt can revoke the old certificate immediately and waive rate limits.

You don’t configure any of this. There’s nothing to schedule. The loop runs whether or not you’re thinking about certificates. If you use CertKit, this is already happening for you.

Shorter lifetimes make this more important, not less

Certificate lifetimes are dropping. The industry is moving to 47 days by 2029, and Let’s Encrypt is going to 45 days by 2028. As lifetimes shrink, the ratio of revocation window to certificate lifetime gets worse. A 24-hour revocation window on a 398-day certificate is manageable. On a 45-day certificate it’s more than half the total validity period.

The CA ecosystem is betting that shorter lifetimes will make bad certificates expire faster and reduce the blast radius when things go wrong. ARI is the other half of that bet: when the CA needs clients to replace certificates quickly, it needs a way to actually reach them. Email isn’t that. A cron job that runs twice a day isn’t that either.

An always-on client polling at the CA’s requested interval is.


CertKit automates certificate lifecycle management.

Comments