Five of my domains expired on the same day and I did not notice for fifty-seven days.
That part is an ordinary story: a batch bought together, renewed together, and lapsing together while the expiry notices went to an inbox I do not read. The interesting part is what happened when I tried to work out which ones I could still save — because I got it wrong, in the expensive direction, and the thing that misled me is written into the spec.
The obvious reading
Query a domain over RDAP and you get back a list of statuses. Mine looked like this:
{
"ldhName": "cavalcante.blog",
"status": [
"client transfer prohibited",
"pending delete",
"redemption period",
"server hold",
"server renew prohibited"
],
"events": [
{ "eventAction": "expiration", "eventDate": "2026-07-26T04:52:32Z" },
{ "eventAction": "last changed", "eventDate": "2026-09-04T04:13:49Z" }
]
}
The generic top-level domain lifecycle, after expiry, runs roughly:
- an auto-renew grace period, where the registrar has not deleted it yet
- the redemption grace period — deleted, but restorable for a fee
- pendingDelete — five days, nobody can do anything
- the drop
So pending delete appears in that list, and pendingDelete is the phase after redemption. The domain is gone. I wrote it off, and I wrote off a second one the same way.
Both were wrong.
What the spec actually says
RFC 3915, which defines the redemption grace period, is explicit. On the RGP pendingDelete status:
A domain in this status MUST also be in the pendingDelete status described in the EPP domain mapping.
Read that carefully, because it is doing something unusual. There are two different pendingDelete statuses — one in the RGP mapping, one in the base EPP domain mapping — and a domain in the redemption grace period carries the EPP one the entire time it is redeemable. Redemption and pendingDelete are not sequential states you can distinguish by name. They overlap by design.
RFC 8056, which maps EPP statuses into RDAP, then collapses both spellings onto the same RDAP token: pending delete. So by the time it reaches you over RDAP, the information you would need to tell them apart is gone.
The only thing that disambiguates is whether redemption period is also present:
redemption period + pending delete → redeemable, restorable for a fee
pending delete alone → the final five days, nothing to be done
Which means the correct rule is the exact inverse of the intuitive one. Redemption has to be checked first. Check pendingDelete first — the obvious ordering, most-severe-wins — and every redeemable domain whose registry happens to emit the redundant token gets reported as unrecoverable.
The tell I had and ignored
My own tooling was telling me the answer was wrong. It computed a drop date of 2026-09-09 — from a last changed of 2026-09-04 plus the five-day pendingDelete window — and printed that on 2026-09-21.
A domain that entered a five-day terminal phase seventeen days ago cannot still be answering queries. The registry was serving me a full record for a name that, by my own arithmetic, had dropped a fortnight earlier. That contradiction was sitting in the output and I read straight past it.
If a tool reports a deadline in the past for a thing that demonstrably still exists, the model is broken. Not the registry.
It is worse than a coin flip, because registries disagree
Here is the part that makes this genuinely nasty rather than just a misreading.
Of my five expired domains, all were in identical condition — same expiry date, same transition date, same phase. But their registries do not describe that condition identically:
| Registry | TLDs | Emits the redundant pending delete? |
|---|---|---|
| Identity Digital | .engineer, .photography, .glass | no |
| CentralNic / XYZ | .audio | yes |
| Knock Knock WHOIS There | .blog | yes |
Both behaviours are correct. RFC 3915 requires the EPP status to be set; it does not oblige the RDAP server to echo it. So the same lifecycle state serialises two different ways depending on who operates the zone.
With the wrong ordering, that split five identical domains into “twelve days left to save this” and “give up, it is gone” — purely on registry verbosity. Not on anything true about the domains.
And the registrar was no help
I had assumed the registrar’s dashboard would at least be consistent with the registry. It was not. Comparing my registrar’s cached view against the registries directly, seven of thirteen domains disagreed — and every disagreement was the registrar asserting a status the registry did not report.
The three that mattered were the registrar adding a phantom pendingdelete to domains the registry still had in plain redemptionPeriod. Believing the registrar there means abandoning recoverable assets. Its record was also visibly stale — timestamps returned as 0001-01-01T00:00:00Z, and status text matching the registry’s state as of two weeks earlier.
None of this is unusual or malicious. A registrar’s copy of registry state is a cache, and caches lag. The mistake was mine: treating a cache as an oracle.
What I would tell you to do
Check redemptionPeriod before pendingDelete. Not after. The intuitive severity ordering is wrong here, and it is wrong in the direction that costs you domains.
Derive deadlines from the registry’s own last changed event, not from arithmetic on the expiry date. The gap between expiry and deletion is the registrar’s choice — anywhere from zero to forty-five days — and it is published nowhere machine-readable. My batch was deleted at day forty. Assume the commonly-quoted forty-five and you invent five days of runway that do not exist.
Do not use last update of RDAP database for that. It is present on almost every response and it is usually today. Mistake it for last changed and every deadline slides to roughly now-plus-the-phase-duration. In my case that moved a real deadline seventeen days into the future.
Treat the registrar as a claim and the registry as the truth, and report the disagreement rather than silently resolving it. A quietly resolved conflict is indistinguishable from no conflict.
Check on a cadence shorter than the shortest phase you care about. pendingDelete is five days. A weekly job can step clean over it and never observe it.
The shape of the bug
What I keep coming back to is that every single ingredient here was reasonable.
Most-severe-status-wins is a sound default. Deriving a deadline from a documented phase duration is sound. Trusting your registrar’s dashboard is entirely normal. The RFC that makes the obvious reading wrong is twenty-one years old and does say so plainly, in one sentence, if you happen to read that sentence.
And the failure was silent. No error, no exception, no malformed data. A confident, well-formatted, precisely-wrong answer — with a date on it — about whether I still owned something.
Those are the ones worth writing down.