Programmable RevenueBuilder Edition Subscribe
Issue 01 The Incident Field

How a shared DNS cluster got our domains blocklisted before their first send

Sending domains started appearing on SURBL before they had sent anything. The cause was not the copy, not the domains, and not the volume. It was the DNS cluster they shared.

Thomas Cornelius August 22, 2026 9 min read
Technical schematic: five domains behind one shared nameserver pair with a SURBL query fanning to all of them, beside three isolated domains each with its own nameserver pair.
One nameserver behind the whole fleet, as a blocklist saw it.

Sending domains in our fleet started appearing on SURBL. Some of them had never sent an email.

That sentence should not be possible. A blocklist is supposed to be a record of behaviour, and a domain that has not sent anything has no behaviour to record. This article is what was actually being recorded, how we found it, and what we rebuilt, in enough detail that you can audit your own fleet against it this afternoon.

The layer most senders never look at

Every domain you register delegates its DNS to a set of nameservers. When a receiving mail server wants to know anything about your domain, where its mail goes, what its SPF record says, whether its tracking subdomain resolves, the answer comes from those nameservers. The delegation itself is public: anyone can ask which nameservers serve your domain, and the registry answers.

DNS is the internet’s directory service. When you register a domain, you tell the registry which “operators” (nameservers) answer questions about it. Most tools that provision domains in bulk park every domain behind the same two operators, because that is the default and nobody thinks about it again. That default is the whole story of this article.

dig NS fleetdom-a.com dig NS fleetdom-b.com dig NS fleetdom-c.com .com registry answers: query type: NS query type: NS query type: NS ns1.shared-dns.net ns2.shared-dns.net same pair, every domain public, passive, correlatable by anyone no cooperation needed
Three NS queries any blocklist can run. The identical answers are the shared attribute.

Sending platforms provision domains in bulk, so the path of least resistance is one shared DNS configuration for everything. Ours worked that way too. Every sending domain in the fleet, grouped behind one nameserver setup. It ran fine for a long time, which is exactly why nobody looked at it.

One calibration before the story, because our setup may not match yours. We send about 15 messages a day per mailbox across a fleet of many domains, so provider volume limits never touched us; what follows is a shared-infrastructure problem, not a volume problem. If you send high volume from few domains, your failure modes live elsewhere.

The obvious suspects

When deliverability drops, the first assumption is always the message. So copy gets rewritten and fresh domains get rotated in. We did both.

The replacement domains were listed too, before they had sent anything. That is the signal that matters, and it is worth pausing on: a domain with zero sending history cannot be listed for its sending. It clears the copy and it clears the domains in one move. Neither warmup nor sending volume had changed either. Several weeks went into those variables before anyone looked at what the listings had in common.

Warmup means gradually building a new domain’s sending activity so receivers learn to trust it, the way a new credit card starts with a low limit. Teams reach for “rewrite the copy” and “rotate in fresh domains” first because those are the knobs their tools expose. The lesson of the incident is that the cause can live in a layer no sending tool shows you.

The pattern in the listings

The listings arrived in clusters rather than one at a time. Domains sharing infrastructure were listed together, within hours of each other. Individual domains behaving badly do not get caught in groups on the same afternoon. Shared configuration does.

The shared piece was DNS. The affected domains sat behind one nameserver configuration, grouped with every other sending domain in the fleet.

THE SHARED SETUP, BEFORE domain 1 domain 2 domain 3 domain 4 domain 5 one nameserver one listing reaches all ONE CLUSTER PER DOMAIN, AFTER domain 1 domain 2 domain 3 own ns pair own ns pair own ns pair no inherited history
The shared setup and its replacement. A listing that keys on the nameserver reaches everything behind it.

What a receiver can actually observe

This incident forced us to write down every attribute of a sending domain that a receiving provider or a blocklist can read without our cooperation. The list is longer than most senders expect: the nameservers, the IP address and its range, reverse DNS, the names on the TLS certificate, the tracking subdomain, redirect and click domains, the links in the message body, the registrar and DNS account, the WHOIS registrant, and repeated brand terms in domain names.

If any one of those matches across two domains, both carry the same risk. That list is now what our provisioning check runs against. Nameserver overlap was on it before the listings began. Knowing about a risk and having burned down the exposure are different things, and this incident was the difference.

The test

We did not want to argue from correlation, so we ran the experiment. We added fresh domains to a nameserver cluster that already carried listings, and other fresh domains to separate, clean clusters.

The domains joining the already-listed cluster were listed straight away. Before sending anything. The domains on their own clusters were not.

SURBL does not document its listing criteria, so we treat this as a repeatable observation rather than a published rule. It was enough to act on.

The change

Every domain we provision now runs on its own DNS cluster: its own hosted zone, its own nameserver delegation, no inherited history. A new domain starts from its own record rather than from the record of everyone it shares infrastructure with.

Two related changes shipped with it, because they close the same class of exposure. Domains are distributed across multiple registrars, so no single account-level action, a suspension, a policy change, can touch the whole fleet at once. And sending domains carry no repeated brand terms: no graph8, no g8, no close variations, because one term repeated across hundreds of domains is a shared attribute you handed to every receiver on a plate.

We do this to avoid creating unnecessary shared attributes, not because we have established that DNS grouping causes listings. That distinction matters. The observation is ours, it is repeatable, and it cost us a fleet’s worth of listings to learn. But we do not claim more than we measured.

Why this gets misdiagnosed

The variables people can see, copy, domain age, volume, warmup, get tested first, because those are the knobs a sending tool exposes. The variable that mattered here belongs to the provisioning layer, and most senders have never once looked at which nameservers their vendor parked their domains behind.

If your domains are getting listed in groups, look at what they share before you look at what they send.

Check it for yourself

Both halves of this story are visible from any terminal. The nameservers your domain shares are public, and SURBL answers over DNS: any 127.0.0.x response means listed.

# The nameservers your sending domain sits behind
dig NS yourdomain.com +short
#   ns1.dnsprovider.com.
#   ns2.dnsprovider.com.

# Ask SURBL about a domain (an answer of 127.0.0.x means listed)
dig yourdomain.com.multi.surbl.org +short
#   (no answer)  = not listed
#   127.0.0.64   = listed

Run the first command across your sending fleet. If every domain returns the same pair of nameservers, you have the setup we had.

On the graph8 platform this isolation is done for you: every domain the platform provisions gets its own DNS cluster, because we made this mistake so builders on the API do not have to.

Still open

Whether registrar diversification materially changes outcomes once DNS is isolated, we do not know yet. The isolation shipped together with the registrar spread, so the incident data cannot separate them, and we would need a controlled split we have not run. If you operate a fleet at similar scale and have data either way, dev@graph8.com reaches us.

Further reading

SURBL’s implementation guidelines document how the list is meant to be queried, and the lists page explains what the answer values mean. Google’s bulk sender guidelines are the receiving-side rules the whole fleet designs against.

The principle we took from it, and the first principle this whole system now runs on: nothing a receiver or a blocklist can observe should connect one of your sending domains to another.

Build with graph8