---
title: "The runbook said the domain was in account A. It was in account B. Verify ownership before touching live DNS."
canonical: https://dxdev.com/blog/runbook-said-account-a-domain-was-in-account-b/
datePublished: 2026-06-02
---
My own build runbook, written by me, confidently told me to flip a DNS record in a specific GoDaddy reseller account. The record wasn't there. The domain actually lived in a completely separate personal account, and the only reason I didn't edit the wrong zone is that the registrar contradicted the runbook a half-second before I started clicking.

Here is the part I want to sit with: the runbook was wrong, and I wrote it. This wasn't stale documentation from some departed engineer. It was a fresh build doc I had authored for an in-progress migration, and it had already drifted from reality. If you take one thing from this, take that. A runbook is a hypothesis about state. It is not state.

## The setup

I was migrating a batch of domains to a new DNS layout. Part of that migration is standing up an off-origin Caddy relay (a tiny DigitalOcean box that auto-issues a Let's Encrypt cert and 301s the bare apex to www), and the final step for each domain is repointing its apex `A` record at the relay's IP. Standard plumbing. The runbook said, in effect, "apex for example.com lives in the reseller portfolio, go edit it there."

So I logged into the reseller SSO, opened the Domain Control Center, searched for the domain, and got: **Domain not found.**

That is the moment. You have two honest moves there, and exactly one of them is fine. You can stop and figure out why the registrar disagrees with your doc, or you can hand-wave it ("must be a search glitch, let me check the other view") and keep going. The wrong move feels faster. It is not.

## The contradiction was already in my own notes

I didn't have to guess. I keep a `.secrets/godaddy.env` with account notes precisely because GoDaddy spreads my domains across more than one login, and those notes said this domain was not in the reseller account at all. It was in my personal customer account, stored in the secrets file. The runbook said the reseller account. The notes said personal account. The registrar said "not found" for the first one. Three sources, and the two that were checkable agreed against the runbook.

The fix was self-serve and took thirty seconds: log out of the reseller SSO, sign in with the stored personal-account credentials, land on the right portfolio, and there's the domain. No need to ask anyone, no need to escalate. The credential was already on disk. If I had trusted the runbook and pushed harder to "find" the record in the reseller account, the best case is wasted time and the worst case is editing a *different* domain's zone because something matched loosely. On live DNS, the worst case takes customer sites down.

## The forwarding lock (the part that would have eaten an hour)

Once I was in the right account, the apex wasn't a normal `A` record. It was GoDaddy's HTTPS-forwarding setup: two anycast `A` records (the provider's documented forwarding front-ends) both marked **Can't edit / Can't delete**.

If you have never hit this, the trap is that the records look like targets you should overwrite, and the UI won't let you touch them. The actual move is counterintuitive: you delete the *forwarding* entry first (the 301 forwarding rule, not the A records), and deleting the forwarding collapses those two locked anycast records into a single editable `A @` pointing at Parked. *Then* you can set that one record to the relay IP. TTL was 600.

The lesson generalizes past GoDaddy: when a registrar gives you records you "can't edit," look for the higher-level feature (forwarding, a managed redirect, a CDN integration) that owns them. The editable record is on the other side of disabling that feature, not in fighting the lock directly.

## The propagation read that almost lied to me

After I set the apex to the relay IP, I checked propagation. Google Public DNS returned the new IP within seconds. If I had stopped there, I'd have called it converged and moved on.

But the authoritative nameservers for the zone, ns17 and ns18.domaincontrol.com, were still handing back GoDaddy's forwarding anycast fleet (the AWS-hosted front-ends the old setup pointed at). Mixed propagation. Google Public DNS had either cached nothing for that name or pulled from an edge that updated early; the source of truth had not caught up yet.

This matters more than aesthetics because of what happens next in the migration. The relay uses Let's Encrypt on-demand TLS, and its http-01 challenge does its own DNS lookup on its own schedule, not on whatever resolver I happen to check with. Checking the zone's authoritative nameservers directly is the reliable way to confirm the change has actually converged at the source of truth, rather than trusting one resolver's cached answer. If I'd trusted the popular public resolver and kicked off cert issuance, the challenge could have hit a host still pointing at the old forwarding, and I'd have spent twenty minutes debugging a "cert won't issue" problem that was really just an unconverged zone. The correct read is `dig @ns17.domaincontrol.com example.com` (ask the source of truth), wait until both authoritative servers return the relay IP, *then* trigger issuance.

Google Public DNS is a convenience. It tells you what one popular resolver currently believes. It does not tell you whether your change is actually live at the zone, and for anything downstream that validates against authoritative servers, the popular resolver's answer is noise.

## The actual takeaway

Three separate things went wrong-adjacent in one ten-minute window, and all three are the same mistake in different clothes: trusting a representation of state instead of the state.

- The runbook *represented* which account held the domain. The registrar held the truth, and they disagreed.
- The forwarding `A` records *represented* the apex. The forwarding feature actually owned them, and you can't edit the representation without addressing the owner.
- A popular public resolver *represented* propagation. The authoritative nameservers held the real answer, and they lagged.

So, concretely, before any live-DNS edit:

1. **Confirm which account and zone actually holds the record at the registrar.** Search it. If the registrar says "not found," believe the registrar over your doc, and go find where it really lives before you touch anything. Documentation drifts; the registrar doesn't lie about what it's authoritative for.
2. **If records won't edit, find the feature that owns them** (forwarding, redirect, managed integration) and disable that first, instead of fighting the lock.
3. **Read propagation at the authoritative nameservers,** not a public resolver like Google's. Especially if anything downstream (ACME, an SSL validator, a partner's resolver) checks the source of truth. Wait for *all* of the zone's NS records to agree before you call it done.

The meta-rule underneath all three: a runbook is your best guess at the world, frozen at the moment you wrote it. The world keeps moving. The five seconds you spend confirming current state against an authoritative source, the registrar, the NS records, the actual API, is the cheapest insurance you will ever buy on a live system. I write the runbooks. I still verify against the registrar every single time, because the version of me that wrote the doc was working from a snapshot, and the snapshot expired.

## Related

- [The GoDaddy reseller Catch-22: the account with the domains has no API, the API account has no domains](godaddy-reseller-catch-22-api-and-domains-in-different-accounts): the multi-account structure that makes account drift like this invisible
- [The GoDaddy "No Public API" Myth: Reverse-Engineering the DCC Internal DNS Endpoint](godaddy-no-public-api-reverse-engineer-dcc-dns): the DCC interface where this verification actually happens
- [A three-reviewer naming cascade for a string 1,308 domains will CNAME to forever](naming-cascade-for-a-string-1308-domains-cname-to-forever): operating at scale across the same domain portfolio, where runbook drift compounds
- [My whole 1,200-domain provider split died instantly: keep a second DoH provider on hand](keep-a-second-doh-provider-dns-google-fallback): verifying propagation at the authoritative source, the same discipline this post argues for
- [The runtime was half dead: use a migration as the audit you'd never run](the-runtime-was-half-dead-migration-as-audit): runbook assumptions meeting a system that had already drifted from what the doc described
