Skip to main content

    ACME Renewal Information (ARI): Letting the CA Set Your Renewal Window

    ARI lets the CA tell your ACME client when to renew: what RFC 9773 defines, the window Let’s Encrypt actually returns, and which clients honour it.

    DR
    Daniel Rehak
    ·
    12 min read
    ·
    Published September 16, 2026
    ·
    Last updated September 16, 2026

    The short answer

    ACME Renewal Information is a small addition to the ACME protocol, standardised as RFC 9773 in September 2025, that moves one decision from your client to the certificate authority: when to renew. Your client fetches a renewalInfo URL and gets back a suggestedWindow with a start and an end, then picks a moment inside it. Most of the time that window lands where you would expect, around two-thirds of the way through the certificate's life. The reason ARI exists is the rest of the time — when the CA has a reason to want that certificate replaced today and no other way to tell you.

    The ACME Renewal Information exchange, from directory lookup to a replacement orderFour steps run left to right. First, the client reads the renewalInfo URL from the ACME directory. Second, it sends an unauthenticated GET for its certificate identifier. Third, the CA returns a suggestedWindow with a start and an end, highlighted as the step where the decision moves to the CA. Fourth, the client renews inside that window and sends a newOrder carrying a replaces field naming the old certificate. A note underneath states that the fourth step is the half most implementations skip.One decision moves from the client to the CA1. DIRECTORYrenewalInfois it advertised?2. GETaki.serialno account key3. THE ANSWERsuggestedWindowstart and end4. NEW ORDERreplacesnames the old certSteps 1 to 3 are what most write-ups describe. Step 4 is what earns therate-limit exemption, and it is the half most implementations skip.Before ARI, every client picked its own renewal time and the CA had no way to correct itexcept by emailing an address that often belongs to nobody in particular.
    The exchange is small enough to read in one pass. The interesting part is not that the CA answers, but that it can change its answer at any moment without you deploying anything.

    What ACME Renewal Information is

    ARI is an extension to ACME, the protocol Let's Encrypt and most automated CAs speak. It adds one endpoint. A client sends an unauthenticated GET to it for a particular certificate and receives a small JSON object: a suggestedWindow with a start and an end, and optionally an explanationURL. That is the entire protocol surface. The IETF published it as RFC 9773, and Let's Encrypt announced the publication on September 16, 2025.

    To see why anyone bothered, it helps to remember what renewal scheduling looked like before. Every client invented its own rule. Certbot renewed when a certificate had thirty days left. Others picked the two-thirds mark. Some administrators set a cron job for the first of the month and never thought about it again. All of these are guesses about a number the CA knows and the client does not.

    That was tolerable while the guess only affected the client. It stopped being tolerable the first time a CA had to replace a large batch of certificates at short notice. A CA in that position has one channel to its subscribers: the email address on the account, which in practice is often a shared alias that nobody reads on a Saturday. ARI gives it a second channel, one that talks to the software instead of the human.

    How the suggested window is worked out

    The RFC deliberately does not say how a CA should choose the window, so the answer depends on whose CA you are talking to. For Let's Encrypt the calculation lives in Boulder, is short enough to read in one sitting, and comes down to three numbers: an offset from the expiry date, a margin either side of it, and one threshold that changes the offset.

    How Let's Encrypt places the suggested renewal window inside a certificate lifetimeTwo horizontal lifetime bars. The upper bar shows a 90-day certificate: the ideal renewal point sits two-thirds along, at day 60, with a highlighted window one percent of the validity either side, running from about day 59.1 to day 60.9. The lower bar shows a 6-day certificate, where the rule changes: because the validity is under ten days the ideal point moves to halfway, day 3, with a window of roughly three hours around it. A note explains the window exists so that renewals disperse instead of arriving all at once.Two-thirds through, unless the certificate is short-lived90-day certificateday 60issuedexpireswindow runs day 59.1 to day 60.9 — two percent of the validity, wide enough to spread the load6-day certificate (validity under ten days)day 3issuedexpireshalfway, not two-thirds — a roughly three-hour window, because there is no room for a second attemptoffset = validity / 3 (or / 2 if validity < 10 days) · margin = validity / 100window = (expiry − offset) ± margin
    The ten-day threshold is the part worth remembering: as short-lived profiles spread, the renewal point moves from two-thirds to halfway and your margin for a failed attempt shrinks with it.

    Boulder takes the validity period, divides it by three, and subtracts that from the expiry date. On a 90-day certificate the ideal renewal point therefore falls on day 60. It then takes one percent of the validity as a margin and puts the window either side of that point, which gives a window about 1.8 days wide, running from roughly day 59.1 to day 60.9.

    The threshold is the part worth writing down. If the validity period is under ten days, the divisor changes from three to two, and the ideal renewal point moves from two-thirds of the way through to halfway. A six-day certificate is therefore scheduled for renewal on day three, inside a window of roughly three hours. The reasoning is not subtle: on a six-day certificate, a renewal attempt at the two-thirds mark leaves you two days to notice a failure and fix it, and two days is not much of a weekend buffer.

    Why a window at all, rather than a single instant? Dispersal. If every client renewed at exactly two-thirds, the CA would see the load pattern of its own issuance history replayed at it, forever. A window lets each client pick its own moment and spreads the traffic out.

    {
      "suggestedWindow": {
        "start": "2026-11-14T08:12:03Z",
        "end":   "2026-11-15T22:48:03Z"
      }
    }

    When the CA needs the certificate gone today

    This is the case ARI was built for, and it works through a trick rather than a new message type. There is no "renew now" field in the protocol. Instead the CA returns a window that has already closed, and every correct client reaches the obvious conclusion on its own.

    A normal suggested window compared with the window a CA returns during an incidentTwo timelines share a vertical marker labelled now. On the upper timeline, the normal case, the suggested window sits in the future and the client waits. On the lower timeline, the incident case, the window is highlighted and sits entirely in the past, starting one hour ago and ending thirty minutes ago, so a client that checks finds a window it has already missed and renews at once. A note adds that the incident response also carries an explanationURL.A window in the past is an instructionnownormalwindowthe window is ahead of you — the client notes it and waitsincident or already revokedwindow−1h−30malready closed, so the next client to look renews immediately; explanationURL says why
    Nothing in the protocol says "renew now". The CA just hands back a window that closed half an hour ago, and every correct client draws the same conclusion.

    Boulder has two triggers for it. If the certificate falls under an open incident, it returns a window starting an hour ago and ending thirty minutes ago, along with an explanationURLpointing at the incident write-up. If the certificate has already been revoked, it returns the same past window with no explanation attached. Either way, the next client to check finds a window it has missed and renews at once.

    Here is the caveat that matters more than the mechanism. ARI can only influence a client that is actually looking. Certbot checks when its timer fires, which on a default install is twice a day, so a window placed in the past is seen within hours. If your renewal job runs weekly because a 90-day certificate never needed more, a CA can move your window as far into the past as it likes and you will find out next Sunday. Supporting ARI and benefiting from ARI are two different things, and the gap between them is a cron schedule.

    The replaces field and the rate-limit exemption

    ARI has a second half that most explanations skip entirely. Asking when to renew is only the first exchange. When the client then places its order, it should include a replaces field naming the certificate being replaced, using the same identifier it used to query the window. This is what turns a renewal into something the CA can recognise as a renewal.

    Boulder enforces three things about that field, and the third is the one with a payoff attached. A certificate may be named by only one replacement order, so a second attempt is refused outright. The new order has to share at least one identifier with the certificate it claims to replace. And if the order is a genuine replacement and it arrives inside the suggested window, it is exempt from rate limits.

    That exemption is worth more than it sounds during exactly the event ARI exists for. In a mass reissue you are asking for a lot of certificates in a short time on names you have already used recently, which is the shape of traffic rate limits are designed to stop. Renewing inside the window is how you tell the CA this is the reissue it asked for, not a runaway script.

    Which ACME clients honour ARI

    Support has moved quickly since the RFC landed, and some of what was written about it in early 2026 is already out of date. The table below reflects what is in each project's source as of September 2026. The pattern to notice is that the two standalone clients enable ARI by default, while the Kubernetes controller still asks you to opt in.

    ClientARI supportWhat that means in practice
    CertbotYes, since 4.1.0 (June 10, 2025)certbot renew checks automatically when the server advertises the endpoint. An early ARI response overrides a later renew_before_expiry, so the CA can pull a renewal forward but your config can still push it back. 4.1.1 stopped checking during --dry-run and for lineages with autorenew off; 5.0.0 remembers Retry-After between runs.
    acme.shYesReads renewalInfo from the directory and sets its next renewal time from the window, storing the explanationURL to print when the renewal happens. An explicit --days wins over the window except when the CA wants the certificate renewed earlier. Set NO_ARI=1 to opt out.
    cert-managerAlpha, off by defaultBehind the ACMEUseARI feature gate since v1.21.0. When enabled it falls back to the existing renewal logic if the CA returns no renewalInfo, and it still respects configured renewal windows. Pilot it rather than assuming a cluster already has it.

    One correction, because it keeps being repeated: several write-ups from earlier this year state that acme.sh has no ARI support at all. That was true once. Its current source implements RFC 9773, including the explanationURL and an opt-out environment variable, and it carries one of the better comments in the ecosystem about why serial number encoding breaks — which is the next section.

    The serial number encoding trap

    The identifier you use to ask about a certificate is built from two pieces joined by a dot: the Authority Key Identifier and the serial number, each base64url-encoded with the padding stripped. Simple enough to implement from the spec in an afternoon, and simple enough to get subtly wrong in a way that only fails against some CAs.

    How the ARI certificate identifier is built and where the DER sign byte goes missingThe identifier is shown as two base64url segments joined by a dot: the Authority Key Identifier on the left and the serial number on the right, both unpadded. Below, two encodings of the same serial are compared. The correct one keeps a leading zero byte, highlighted, which DER adds whenever the first byte is 0x80 or higher. The incorrect one, taken straight from OpenSSL hex output, omits it. A note records that Boulder accepts both forms while Sectigo rejects the order with HTTP 401.One byte decides whether your order is acceptedbase64url, unpaddedAuthorityKeyIdentifier.base64url, unpaddedserialNumberDER value bytes, first byte is 0x80 or higher:00A3 F1 ... serial bytescorrect — DER keeps the integer positiveWhat openssl x509 -serial prints:A3 F1 ... serial bytessign byte droppedBoulder accepts either form. Sectigo rejects newOrder with HTTP 401, and about half of all serials are affected.
    Any serial whose first byte is 0x80 or higher needs the sign byte, which is half of them on average — so this fails intermittently and looks like a CA problem rather than an encoding one.

    RFC 9773 asks for the DER-encoded INTEGER value bytes of the serial. DER represents signed integers, so when the first byte of a serial is 0x80 or higher it prepends a 0x00 byte to keep the value positive. The hex that openssl x509 -serial prints does not include that byte. Encode it straight from the OpenSSL output and roughly half your certificates — every serial whose first byte happens to land at or above 0x80 — carry an identifier one byte short of what the spec describes.

    Whether that matters depends entirely on the CA. Boulder accepts the serial either way, so against Let's Encrypt the bug is invisible and can sit in a codebase for years. Sectigo, which issues for ZeroSSL, checks strictly and rejects the order with HTTP 401 and the message replaces field does not identify a certificate. The failure looks random, because it depends on a serial number you did not choose, and it looks like the CA's fault, because the same code works elsewhere.

    Why ARI matters more every year

    Certificate lifetimes are on a published downward schedule. Under ballot SC-081v3 the maximum TLS certificate validity dropped to 200 days on March 15, 2026, falls to 100 days on March 15, 2027, and reaches 47 days on March 15, 2029. Each step compresses the distance between a renewal that quietly failed and an outage.

    At 47 days the two-thirds mark is day 31, leaving sixteen days of slack. That is still workable. What changes is the cost of getting the schedule wrong, and the value of a CA being able to correct it without waiting for you to read an email. The ten-day rule in the window calculation is a preview of where this ends: on short-lived profiles the renewal point has already moved to halfway, because two-thirds no longer leaves room to retry. Which of those profiles you are actually on is something you now choose per order: ACME certificate profiles covers what each one changes and what it breaks.

    Worth being clear about the scope, though. ARI is part of ACME, not part of X.509 or the Baseline Requirements, so it exists wherever an ACME server chooses to implement it and nowhere else. If you run organisation-validated or extended-validation certificates ordered through a portal rather than an ACME endpoint, there is no renewalInfo URL in the picture at all, and renewal timing stays with whatever tracks your expiry dates. That is a reasonable trade for certificates that need a human validation step anyway — it just means the automation story for OV and EV certificates is a monitoring problem rather than a protocol one.

    Querying ARI yourself

    The endpoint takes an unauthenticated GET, which means you can read your own renewal window without your account key and without touching your client's state. Start by asking the directory whether the CA offers it at all. If the field is absent, the CA does not implement ARI and nothing else here applies.

    curl -s https://acme-v02.api.letsencrypt.org/directory | jq -r .renewalInfo

    Then you need the two halves of the identifier out of the certificate. The Authority Key Identifier is an extension; the serial is a field. Remember the sign byte from the previous section when you encode the serial.

    openssl x509 -in cert.pem -noout -serial \
      -ext authorityKeyIdentifier

    Appending base64url(AKI).base64url(serial) to the renewalInfo URL and fetching it returns the window. If you would rather not assemble identifiers by hand just to confirm what a live server is serving, the SSL checker and certificate tools read the certificate off the handshake and show you the dates the calculation is based on.

    Frequently Asked Questions

    Get instant answers to common questions about SSL certificates and our services.

    Still Have Questions?

    Our SSL experts are available 24/7 to help with any questions about certificates, installation, or technical issues.

    Certificates that renew on someone else's schedule

    ARI only reaches certificates issued over ACME. For everything else, the equivalent safety net is knowing an expiry date is approaching before a browser does. Our certificate tools read expiry and chain data straight off a live host, which is the same information an ARI window is derived from.

    Related reading