genv.

IntegrationsDomain renewal failures, and how to reconcile them

15 min readPublished Reviewed By the GENV team

In short

When a renewal answer is lost, do not retry. An unchanged expiry date does not prove nothing happened — the renewal may still be pending, or the read may be stale — and a changed one does not prove your request changed it, because an automatic renewal or somebody else can move it too. Settle the outcome from the registrar's own record of that request, in the terms its documentation says are final. Until you have that, the outcome is unknown, and it stays unknown.

Domain renewals fail in a particular way: the request is a purchase, the answer can be lost, and the domain carries a date that looks as though it should settle the question. On its own it does not. What makes getting this right urgent is the timeline — the consequences of a mistake escalate on a schedule you do not control.

The expiry timeline for gTLDs

ICANN's Expired Registration Recovery Policy sets out what registrars must do around expiry for generic top-level domains, including the notices before expiry and a period after it during which the registrant can recover the name. After that recovery period a domain typically enters redemption, where restoring it carries a separate restore fee — the policy requires registrars to publish it — and then it is released.

The operational consequence: notice earlier for domains than for hosting. A hosting customer who misses a renewal has a suspended website; a domain customer who misses one can lose the name, and with it their email.

Why the expiry date does not settle it

The expiry date is evidence, and it is worth recording before every attempt. It is not proof in either direction.

  • Unchanged does not mean nothing happened. A registrar can accept a renewal and complete it later. EPP allows a server to receive a transform command and defer completing it (RFC 5731, §3.2), and a registrar's own API may queue orders the same way. A read can also come from a cache or a replica that has not caught up.
  • Changed does not mean your request changed it. Depending on the registrar and the TLD, a domain can be renewed automatically around expiry, and anybody else with access — the customer at the registrar, a colleague, another system — can renew it too. A date that moved by exactly the term you asked for is consistent with your renewal; it does not show that your renewal is what moved it.
  • Moved too far is not proof of a double renewal either. It is worth raising with the registrar at once, but it can equally be your renewal plus an automatic one, or yours plus somebody else's.

The reconciliation, step by step

  1. Stop. Do not send the renewal again.
  2. Ask the registrar about the request, not only about the domain. Look for what its documentation treats as authoritative for an order: a transaction or order status query, a transaction history, a reference returned when the request was accepted. Rely on what the documentation says is final, and on nothing it does not.
  3. Read the domain as well — an info call is a read, and is safe to repeat — and compare the expiry date with the one you recorded before the attempt. Treat that comparison as corroboration, not as the answer.
  4. If the registrar's record shows the renewal completed, and its documentation says that record is final, record it as succeeded, with the registrar's reference.
  5. If the record shows the request was refused or never processed, in terms the documentation says are final, record that. Only then is a deliberate new attempt safe.
  6. If the record says pending, or the registrar offers no documented way to find out, the outcome is still unknown. Keep it unknown, raise it with the registrar, and do not retry until they have answered.

Record the expiry date before every attempt anyway. It is the cheapest corroborating evidence you have — just not the deciding evidence.

Guarding against the double renewal in advance

EPP's renew command carries the domain's current expiry date, and RFC 5731 gives the reason: it ensures repeated renew commands do not result in multiple, unanticipated successful renewals. Some registrar HTTP APIs offer the same guard as a parameter. Where yours documents one, send it.

Be clear about what it protects. It refuses a repeat once the first renewal has moved the date. While the first is still pending the date has not moved, so the guard cannot tell a repeat from a first attempt. It makes a mistaken retry cheaper; it does not replace the reconciliation above.

What a lost answer is not

Classifying registrar answers to a renewal — check each row against your registrar's documentation
What came backWhat it meansWhat to do
A code the registrar documents as a refusal with no action takenThe registrar declinedRecord the reason. Correct it and try again deliberately
An accepted or pending responseThe registrar has the request and has not finished itPending. Follow the documented status; do not retry
An unrecognised codeYou do not know what happenedUnknown. Reconcile with the registrar
Nothing — a timeoutThe request may have been processedUnknown. Reconcile with the registrar
A rate-limit responseUnknown, unless the registrar documents that a rate-limited request is never processedReconcile with the registrar
A redirectSomething other than the documented endpoint answeredUnknown. Reconcile, and investigate the endpoint

The first row and the unrecognised code are the distinction that matters most. Mapping every non-success to "refused" is a claim that nothing happened — and after a purchase, that is a claim you can only make from a code the registrar documents as meaning exactly that.

Telling the customer

A domain in an uncertain state is worth a proactive message. "We are confirming your renewal with the registrar and will update you today" costs nothing and can head off the support ticket that starts with "my email has stopped working". Keep the customer-facing status honest: renewing is not renewed.

Where GENV is

GENV's registrar adapters classify outcomes into five states, including an explicit ambiguous one: an unrecognised or missing response code after an effecting write is treated as unknown, never as a refusal. An unknown registrar request is never retried automatically — somebody establishes what happened and records it, and the record says it was reconciled, which is a different claim from the registrar having said so. Renewals are not routed to real registrars in the shipped build.

Questions

How early should renewal notices go out for domains?

Earlier than for hosting. For gTLDs, ICANN's Expired Registration Recovery Policy requires the registrar to send at least two reminders — approximately one month and one week before expiry — and another within five days after it. If you resell, set your own schedule knowing the registrar's notices may reach the same customer, and leave room for a failed payment to be fixed before the name is at risk.

What if the registrar shows a different expiry than the registry?

Then you have a reason to look closer, not an answer. The registry's date is the deadline that governs the name, but depending on the TLD it can move at expiry through an automatic renewal the registrar may later reverse, and a registrar's display can lag behind. Neither date tells you whether your request was processed; the registrar's record of the request does.

Can I automate the reconciliation?

You can automate gathering the evidence: the registrar's documented status or transaction queries, the domain read, the comparison with the recorded date. Automate the conclusion only where the registrar documents that a particular answer is final. Everywhere else, make the conclusion a recorded act — who or what established it, and from which evidence — so that an audit can tell "the registrar confirmed it" from "somebody assumed it".

Sources

  1. ICANN — Expired Registration Recovery Policy
  2. RFC 5731 — EPP Domain Name Mapping
  3. ICANN — Transfer Policy

Official documentation, each requested on 21 September 2026. Provider behaviour changes; check the source before relying on a detail.