← All posts

Nobody agrees when your domain expires

· 9 min read
clidomainsrdapwhois

Ask the internet when google.com was last updated and you’ll get 2 August 2024.

Ask it again, slightly differently, and you’ll get 9 September 2019.

Both answers are live right now. Neither is a cache artifact or a bug. They come from two of the four places that will answer questions about a domain, and those four places do not agree. Not about this domain, and not about most domains.

Four sources, four answers

There is no single authority on a domain name. There are two, and each of them publishes what it holds twice.

The two authorities hold different records, not copies of one. The registry operates the top-level domain and knows what is in the zone. The registrar sold you the domain and holds the customer relationship. Each keeps its own account of the name, and neither is obliged to match the other.

Each publishes over two protocols. WHOIS is plaintext over port 43, first specified in 1982; its current RFC defines how to open the socket and nothing whatsoever about the shape of the reply, which is why no two servers format one the same way. RDAP is its replacement: structured JSON over HTTPS, genuinely specified, and not universally deployed.

The two protocols are also mid-changeover, and the changeover is contractual rather than a matter of taste. ICANN’s 2023 amendment to the base gTLD registry agreement set a WHOIS Services Sunset Date of 28 January 2025, after which serving registration data over the WHOIS protocols — port 43 and the web form alike — stopped being an obligation.

Ceasing to be obliged is not the same as switching off. Some have, some have not, each on its own timetable, and ccTLDs were never under the obligation in the first place. What is left is a patchwork you cannot predict from the name.

Of the fourteen domains behind this post’s figures, vercel.app answers on RDAP only, its WHOIS gone. github.io answers on WHOIS only, because .io has no RDAP. Four more have a registry still serving WHOIS while their registrar’s port 43 has gone dark. So querying both protocols is not belt and braces. It is the only way to see the whole record while the changeover has no agreed finish date.

Two authorities, two protocols, four sources: registry RDAP, registrar RDAP, registry WHOIS, registrar WHOIS. Each of them will happily answer a question about the same name.

That structure tells you where to expect trouble. One authority’s two sources are usually two views of a single set of records, so they tend to agree with each other. The gaps that matter open between the registry and the registrar. Below, all four are asked when google.com was last updated: watch the two registrar answers say one thing and the two registry answers say another. The bars are the real time each took to reply.

RR
672ms
GR
279ms
RW
392ms
GW
123ms
updated as reported by each source for google.com
RR2024-08-02T02:17:33.000+00:00
GR2019-09-09T15:39:04Z
RW2024-08-02T02:17:33+0000
GW2019-09-09T15:39:04Z

google.com · updated · captured 2026-08-20 with plat 0.4.0 · replay scaled to 1.4s — bar length and arrival order are real measured latency

One field. Four answers. Two of them five years apart.

Nobody is lying. The registrar knows about a change it made in 2024 that never needed to reach the registry. The registry is reporting the last time its record moved. Both are accurate answers to subtly different questions, and both are returned under the same field name.

This is the normal case, not the pathological one. Of the first nine domains I looked at while writing this, four disagreed about updated.

When is a disagreement real?

Before you can resolve a disagreement you have to establish that there is one.

Look again at the four values above. The two registrar sources report 2024-08-02T02:17:33.000+00:00 and 2024-08-02T02:17:33+0000. Those are different strings. They are the same instant.

So the first job is not merging, it is refusing to count formatting as disagreement. Trailing periods, casing, whitespace, timestamp precision, +0000 versus Z. None of it is a fact about the domain. Toggle it away:

3 distinct values
updated as reported by each source for google.com
RR2024-08-02T02:17:33.000+00:002024-08-02T02:17:33.000Z
GR2019-09-09T15:39:04Z2019-09-09T15:39:04.000Z
RW2024-08-02T02:17:33+00002024-08-02T02:17:33.000Z
GW2019-09-09T15:39:04Z2019-09-09T15:39:04.000Z

google.com · updated · captured 2026-08-20 with plat 0.4.0

Three distinct strings become two distinct positions.

Three values become two. What survives is the real disagreement, and now it is the only thing left to look at.

It is worth being precise about how far this goes, because it is tempting to keep going. Comparing timestamps as instants is safe. Lowercasing is safe. But hover.com reports its registrar as TUCOWS.COM, CO. from one source and Tucows Domains Inc. from another, and no normalisation rule resolves that, because it is not a formatting difference. It is the same company under two names. A tool that quietly picked one and moved on would be inventing a fact. We will come back to it.

Somebody has to win

Two answers, one field. Something has to be returned.

The ordering is not arbitrary. The registrar is closest to the domain: it made the change, so it goes first. RDAP is preferred to WHOIS because it is structured rather than scraped. That gives registrar RDAP, registry RDAP, registrar WHOIS, registry WHOIS, and every field takes the first source down that list with something usable on it.

“Something usable” is doing real work in that sentence. A source can fail to supply a field without failing at all. A registrar’s RDAP server can answer perfectly and simply not carry a registrar URL. A redacted value is present and useless. Both cases fall through to the next source in the same way.

Here is godaddy.com’s registrar URL. It has already fallen twice before you touch anything: neither RDAP source carries the field at all. Silence a source and watch it fall again:

Sources in precedence order, highest first. Click a source to silence it and see what the answer becomes without it.

  1. RRreported nothing for this field
  2. GRreported nothing for this field
  3. https://www.godaddy.com
  4. http://www.godaddy.com

plat returns

godaddy.com · registrar.url · captured 2026-08-20 with plat 0.4.0

Silence a source to see what the answer would have been without it.

Drop the registrar’s WHOIS and you get the registry’s answer: the same URL, one scheme worse. That is what a fallback costs you here. It is rarely nothing.

And the ladder is often shorter than four. vercel.app answers from registry RDAP alone. github.io has no RDAP at all. Both its answers come from WHOIS servers. Any tool that assumes four sources, or assumes RDAP exists, is writing fiction for a meaningful share of the internet.

Except when winning is wrong

Precedence is a good rule. Here is a domain where following it hands you the wrong answer to the question you asked.

GoDaddy is the largest registrar in the world. Ask GoDaddy when godaddy.com expires and it says 1 November 2126. Ask Verisign, which actually operates .com, and it says 1 November 2032.

RR2126-11-01T06:59:59Zwhat precedence alone picks
GR GW2032-11-01T11:59:59Zwhat plat returns

94 years apart. On a genuine conflict expires takes the earliest disputed date rather than the highest-precedence one — assuming more runway than you actually have is the more expensive mistake.

godaddy.com · captured 2026-08-20 with plat 0.4.0

The one field where the highest-precedence answer loses on purpose.

Ninety-four years is a strange sort of typo, and it almost certainly isn’t one.

A .com domain does not lapse because a date went by. It auto-renews at the registry: Verisign renews it, bills the registrar, and the name carries on resolving. A domain only goes away if the registrar affirmatively deletes it. Registrars drive that decision from their own expiry field. Push that field most of a century out and your own automation never comes for the name. It simply keeps auto-renewing at the registry, indefinitely. Which is a reasonable thing to want, when the name is your company.

So this is not a right answer next to a wrong one. Verisign’s 2032 is when the current registration term ends. GoDaddy’s 2126 is closer to a declaration: this one is never going anywhere. Both are true. They are answers to two different questions, returned under the same field name. That is the whole problem of this post, arriving in a single field.

Only one of them is actionable, though. Anything asking a domain for its expiry date is really asking when the thing needs attention, and being wrong about that is not symmetric. Believe a domain expires later than it does and you find out when it stops resolving. Believe it expires sooner and you renew something early. One of those is a bad afternoon and the other is an outage, so the earliest disputed date wins even though it comes from the lower-precedence source.

That is not a merge algorithm. It is a judgement about which failure you would rather have, expressed as one.

Every field in a reconciled record has an answer to that question, whether or not anyone wrote it down. Most of them just answer it by accident.

Showing your work

Which brings us back to Tucows.

The honest response to TUCOWS.COM, CO. versus Tucows Domains Inc. is not to pick a winner. It is to return a value and say who supplied it, so that a caller who cares can see the disagreement and one who does not can carry on. Every field, its own provenance:

Every field, with the sources that agreed on its value. Click a field to see what all four said.

registrar.nameTUCOWS.COM, CO.RR RW
RRTUCOWS.COM, CO.
GRTucows Domains Inc.
RWTUCOWS.COM, CO.
GWTucows Domains Inc.
registrar.urlhttp://tucowsdomains.comRW
RRnot reported
GRnot reported
RWhttp://tucowsdomains.com
GWhttp://www.tucows.com
registrar.abuseEmaildomainabuse@tucows.comRW GW
RRnot reported
GRnot reported
RWdomainabuse@tucows.com
GWdomainabuse@tucows.com
created1996-07-12T04:00:00ZRR GR RW GW
RR1996-07-12T04:00:00Z
GR1996-07-12T04:00:00Z
RW1996-07-12T04:00:00Z
GW1996-07-12T04:00:00Z
updated2026-06-12T04:18:14ZRR GR RW GW
RR2026-06-12T04:18:14Z
GR2026-06-12T04:18:14Z
RW2026-06-12T04:18:14Z
GW2026-06-12T04:18:14Z
expires2027-07-11T04:00:00ZRR GR RW GW
RR2027-07-11T04:00:00Z
GR2027-07-11T04:00:00Z
RW2027-07-11T04:00:00Z
GW2027-07-11T04:00:00Z
nameserversns1.tucows.com, ns2.tucows.com, ns3.tucows.comRR GR RW GW
RRns1.tucows.com, ns2.tucows.com, ns3.tucows.com
GRns1.tucows.com, ns2.tucows.com, ns3.tucows.com
RWns1.tucows.com, ns2.tucows.com, ns3.tucows.com
GWns1.tucows.com, ns2.tucows.com, ns3.tucows.com
statusserverDeleteProhibited, serverTransferProhibited, serverUpdateProhibitedRR GR RW GW
RRserverDeleteProhibited, serverTransferProhibited, serverUpdateProhibited
GRserverDeleteProhibited, serverTransferProhibited, serverUpdateProhibited
RWserverDeleteProhibited, serverTransferProhibited, serverUpdateProhibited
GWserverDeleteProhibited, serverTransferProhibited, serverUpdateProhibited

hover.com · captured 2026-08-20 with plat 0.4.0 · 2 conflicts

Open any field to see all four sources. Two of these disagree.

This is plat, the tool every figure in this post is output from: one command that speaks both protocols.

Doing this by hand means running whois, following its referral chain from IANA to the registry to the registrar yourself, reading whatever unlabelled text comes back, then reaching for a separate RDAP client and holding both answers in your head to compare them. plat does the discovery for both: IANA’s bootstrap file for RDAP, the referral chain for WHOIS. It queries all four sources concurrently and returns one record with the sources marked against each field. RDAP and WHOIS, registry and registrar, in a single lookup.

The part I would defend hardest is not the merging. It is that provenance is not a display option. In the Go library the record type is built from Field[T]: a value together with the sources that supplied it. There is no way to pull a value out without the question who said this? coming with it. A lookup also succeeds as long as one source answers, because a dead registrar is a normal Tuesday, not an exception worth throwing.

You can install it:

brew install patramsey/tap/plat

plat google.com             # both protocols, all four sources, one record
plat google.com --conflicts # and show me every value they disagreed on
plat google.com -o json     # the same record, for something downstream

Every figure in this post is real captured output, stamped with the date and the version that produced it. Run it yourself and the numbers will have moved. That is the point, not a caveat.

Because none of this resolves. There is no later version of the system where the four sources agree. Two parties keep two sets of books, for two different reasons, and publish them four ways. GoDaddy’s 2126 is not a bug awaiting a fix. It is what GoDaddy means.

So run whois on something tomorrow. You will get one answer, cleanly formatted, with no indication that it is one of four.

It always was.