Skip to main content

Does www Still Work?

This started as a vocabulary question I couldn't answer cleanly.

Someone asked me what a TLD actually is, and I gave the normal answer — the last label, the rightmost thing, .com and .dev and .social. Fine. But saying "the last label" out loud makes you notice that a hostname is just a list of labels, and that nothing in the system cares which one is which. com is a label. example is a label. And www is a label.

That's when it got annoying. Because if www is just a label, why does it feel like part of the protocol?

www was a filename for a machine

It never was part of anything. In the early web you named machines after their jobs. The box running the HTTP daemon got called www, the file server got ftp, the mail exchanger got mail, and the one nobody talks about anymore got gopher. www.example.com meant "the web machine at example.com," in exactly the way db3.internal means the third database.

Nothing about it is reserved. There is no RFC that says a resolver should try www if the bare name fails. It's a convention that got so common it stopped looking like one.

Then DNS added a wrinkle that kept the convention alive past its natural life. You can't put a CNAME at the apex of a zone — the apex has to carry SOA and NS records, and a CNAME isn't allowed to coexist with other records at the same name. So for years, if you wanted your site behind a CDN, pointing www at it was a one-line CNAME and pointing the bare domain at it was a research project. www was the easy one. The apex was the one you had to work for.

Providers eventually papered over that — Route 53 alias records, ALIAS and ANAME at various registrars, CNAME flattening at Cloudflare. And once the apex became easy, the ordering flipped. The bare domain became the canonical one, and www became the afterthought.

Which raises the actual question. If www is now an afterthought, is anyone still bothering?

I started with my own sites

I own four domains that serve something: thomasrones.com, csv-helper.com, apresapply.com, and fxf.social.

www works on zero of them.

Not "redirects badly." Not "serves the wrong cert." ERR_NAME_NOT_RESOLVED — the name does not exist. There's no record there at all. Anyone who typed the habitual www. in front of my domain got a browser error page and no reason to try again.

One detail from the network panel I liked: on the domains with HSTS, the failure is preceded by a 307 with no remote address. That redirect never left my machine — it's the browser upgrading http:// to https:// internally, before it touches the network at all. Confidently rewriting a request to a name that doesn't exist is a funny way to fail.

They're fixed now. That turned out to be a longer story than "add an A record" — the name has to resolve and whatever terminates TLS has to recognize the hostname and hold a certificate covering it, which on my setup means alias records plus alternate domain names plus a re-issued cert, and the details differ for the ones without a backend. That's its own article and I'm not going to bury it in this one.

Four data points is an anecdote

Here's the part I actually can't answer: is this a me problem?

I have a story either way. If most of the web has quietly dropped www, then my sites were normal and the convention is dead and typing www. is a habit that fails often enough to notice. If most of the web still handles it, then I shipped four broken sites and told myself a story about deprecation to feel better about it.

Four domains distinguishes between those exactly as well as zero domains does.

So the question needs a real denominator. Take a large list of active domains — hundreds of thousands, ideally a million — and ask the same set of questions of each one.

What "does www work" actually decomposes into

The naive version is one boolean: does www.<domain> resolve. That boolean is wrong in both directions, which is most of what makes this interesting.

It's wrong on the false-positive side because resolving isn't serving. A wildcard record — *.example.com — makes www resolve, and asdfjkl resolve, and every other label you can invent resolve, and none of them necessarily answer HTTP. A zone with a wildcard scores 100% on the naive test while potentially serving nothing at that hostname. If I don't separate NXDOMAIN from "resolves and then does nothing," I'll count wildcards as support and inflate the number.

It's wrong on the false-negative side because there's a whole ladder of ways to resolve and still be broken, and they mean different things. The name resolves but nothing accepts a TCP connection. Something accepts the connection but the TLS handshake fails because the certificate has no SAN entry for www. TLS completes and the server returns a 404 because the vhost only knows the apex. Each of those is a different mistake by a different person, and flattening them into "no" throws away the finding.

And then there's the direction question, which is the one I actually care about culturally. For domains where both names work, who's canonical? Does www 301 to the apex, does the apex 301 to www, or do both serve 200 independently with no canonical form at all — which is the SEO-duplicate-content case people used to write blog posts about.

So per domain, the record I want is roughly: does the apex resolve and what record type, does www resolve and what record type, can each complete a TLS handshake, does the certificate actually cover the name presented, what status does each return, and where does each redirect chain terminate. Compare the two terminal hosts and you get the canonical direction. Compare the failures and you get a taxonomy of how people break this.

One constraint on all of it: no browser anywhere in the pipeline. Browsers are actively unhelpful here. The omnibox does its own fixups and will try adding or stripping www on your behalf. The HSTS preload list rewrites the request before DNS is consulted. A single Enter keypress produces a pile of rows, of which exactly one is the answer and the rest is the browser speculating. Every one of those obscures the thing I'm trying to measure. This needs a raw resolver and a raw HTTP client that do what they're told, report a redirect instead of quietly following it, and describe a timeout as a timeout.

Why this becomes a tool instead of a shell loop

You can do one domain in bash. dig, curl -sSI, read the output. Fine for four.

The problem is that every single one of those checks is the same shape: send a small thing, wait a long time, get a small thing back. A DNS query is a few hundred bytes and tens to hundreds of milliseconds. A TLS handshake is two round trips before a single byte of HTTP moves. Call it 300ms of mostly-idle waiting per domain if nothing goes wrong, and considerably more when it does, because the interesting failures are the ones that time out rather than refuse.

A million domains, one at a time, at 300ms each, is about three and a half days of a laptop doing nothing but waiting. And that's the good case — a stalled connection to a dead host costs whatever timeout I set, not 300ms.

That's a real reason to care about concurrency rather than a synthetic one. I'm not writing another "look, Go can start 100,000 goroutines" demo where the goroutines do nothing and the number is meaningless. The work here is genuinely I/O-bound and genuinely parallel, and the ceiling isn't the CPU — it's whatever gives out first when you push the worker count from 10 to 100 to 1,000 to 10,000. File descriptors. Ephemeral ports. The resolver deciding you're abusive. Connection pool behavior when most connections fail. Memory held by ten thousand in-flight response buffers.

I don't know which of those breaks first on this workload. Finding out is most of the appeal.

And a million isn't where I want to stop. The version of this I actually want is internet-scale — hold a working set of every active domain, on the order of a billion names, and ask how fast the whole thing can be classified. At that size a second class of problem shows up that a million domains lets you ignore. A billion records is not a slice you keep in memory, so the input has to stream and the output has to land somewhere durable while the scan is still running. The results are small per domain and enormous in aggregate, and they have to stay small — this runs on a laptop, so however many bytes I spend per domain gets multiplied by a billion and then has to fit on a disk I also use for other things. Resumability stops being a nicety, because nothing that runs for hours survives its first crash otherwise. Where the data lives becomes a design decision with a throughput cost attached, rather than a detail you settle by appending to a CSV.

So the next articles are the scanner itself — how it's built, and what happens to it under load. Whether that's one article or two depends on where the interesting parts turn out to be, and I'd rather decide that after the thing exists than promise a structure now.

Then the results: what fraction of the web still answers to www, which direction the redirects point, and how many other people shipped the same thing I did.

And if the scan is cheap enough to repeat, the results stop being a single number and start being a series. A State of the WWW report, run on a schedule, tracking whether the convention keeps decaying or quietly comes back. Mostly a joke. But a number you can only take once is a fact, and a number you can take every quarter is a trend, and the second one is worth considerably more than the first.

Where I've landed so far

Two things I'm fairly confident of before running anything.

www is not special and never was. It's a hostname with good PR. Everything that makes it feel structural is habit — yours, mine, and the browser's, which is the only one of the three that's been quietly compensating for the gap.

And I broke it on four sites without noticing, which means the feedback loop on this is terrible. Nothing monitors a hostname you never configured. There's no alert for a name that doesn't exist. The only signal is a person typing the old habit into the address bar and quietly deciding your site is down.

The rest of it — whether that's common or whether it's just me — I'll have a number for shortly.

I'll admit the scan is not entirely about www. Most of what I build is a CRUD app where the load is a handful of requests in a day, and you can write those for years without once meeting the limit of anything. Nothing pushes back. This workload pushes back on the first try, and the whole appeal is finding out which wall I hit first.

Comments

No comments yet. Be the first!