---
title: "Why Our MCP Endpoint Resolved to a Tunnel We Had Already Retired"
canonical: https://dxdev.com/blog/dns-staleness-on-topology-migration/
datePublished: 2026-08-09
---
Yesterday we moved our knowledge server off a local tunnel and onto a real cloud endpoint. Same MCP tools, same agent, new address. We ran a full session against it. Search worked, reads worked, drops worked. We closed the laptop feeling like the migration was done.

This morning the same agent couldn't reach the same server. It didn't return an error. It refused to connect, then timed out, then connected to something that clearly wasn't our new box. We hadn't touched the config since the successful run twelve hours earlier.

## Debugging the wrong layer for twenty minutes

Our first move was to assume we'd broken the server itself. We checked the process, checked the port, checked the reverse proxy logs. Everything on the new box was healthy and waiting for traffic that never arrived. So the problem was how our agent was finding the destination.

We ran a direct DNS lookup against the record our MCP config pointed at. It resolved to an IP that belonged to the old topology, the local tunnel endpoint we'd just retired. Our own resolver was still handing out yesterday's answer. The record had been updated correctly at the source. What hadn't caught up was every cache between our machine and the authoritative nameserver, each holding the old answer for whatever TTL it had cached before we made the change.

The deploy was done. DNS wasn't. Those are two different finish lines, and we'd only crossed one of them.

## The postmortem we already had

We had the write-up for this exact failure sitting in our own knowledge archive before it happened to us. During a large domain migration we ran for customer sites, one client's domain went down because a DNS flip landed before everything downstream was ready to receive it. That incident is why the client-managed domain rollout now runs on a self-serve model with a hard deadline, instead of us flipping records on client-owned domains directly. It's also why there's a [fail-closed guard](/blog/live-guard-rollback-untested/) so the migration engine can't take a client site offline if something is inconsistent at cutover.

So we had built guardrails against DNS staleness for other people's domains, then walked straight into the same problem on our own infrastructure. The server was stood up in an afternoon with none of those guardrails, because it felt too small to need them.

## Why the lag stays invisible

Everyone knows in the abstract that DNS propagation takes time. From where you're standing, though, the delay can't be seen. Your deploy script exits zero. Your new server logs a clean startup. Every signal you actually watch says the migration succeeded. The only thing that hasn't caught up is a distributed cache you don't control and can't directly inspect, sitting between you and the agent that's about to use the thing you just built.

It also doesn't announce itself as staleness. It shows up as a connection failure, which looks exactly like a broken deploy, which sends you debugging the wrong layer.

For agent infrastructure this matters more than it did for the web servers we're used to migrating, because the agent doesn't stop to wonder whether something is off. It gets a timeout, retries, gets another timeout, and either fails the task or silently falls back to whatever it can still reach. If we'd kicked off an unattended overnight run against that endpoint instead of testing by hand first thing, we wouldn't have found a broken connection. We'd have found a run that did nothing, or did the wrong thing, and we wouldn't have known until we went looking for output that wasn't there.

## What we check now

Any time we change network topology, whether local to cloud, direct to tunneled, or one provider to another, "the deploy succeeded" no longer means "the path is live end to end." We check the record against the authoritative nameserver directly, bypassing our own resolver, since our resolver is the thing most likely to be lying to us from cache. And we don't hand a freshly migrated endpoint to an agent for an unattended run until we've confirmed a clean connection from a machine that has never talked to the old address, so there's no cache of its own to fool us.

None of this is exotic. It's the lesson the large domain migration already taught us across a big batch of customer domains: cutover and propagation are two separate events, and the gap between them is where things break. We hadn't carried that over to a single server we stood up for ourselves, the one without a project plan and a deadline attached to it.

A finished deploy does not mean the path is live, because cutover and propagation run on separate clocks. After any topology change, ask to see the DNS record checked against the authoritative nameserver and a clean connection from a machine that has never used the old address. Do that before any unattended agent run depends on the new endpoint.
