โ† deemwar engineering examples Runnable ยท Node ยท zero deps ยท free

Your reconnect loop never notices DNS came back.

A reconnect loop that resolved the hostname once, before the retry loop started, keeps retrying that first IP forever โ€” even long after a DNS failover moved the record somewhere reachable. The process never crashes. It just retries a connection that can never succeed again, and looks exactly like "still down," indefinitely, until something restarts it.

The crux

function naiveReconnectLoop(resolve, maxAttempts) {
  const ip = resolve('chat.example.com'); // resolved ONCE, before the loop
  for (let i = 0; i < maxAttempts; i++) {
    if (connect(ip)) break; // always the same ip
  }
}

That reads like a reconnect loop and behaves like a retry-forever loop against one fixed address. The fix is one line of scope โ€” move the resolve call inside the loop โ€” but it's easy to miss, because the code compiles, the loop runs, and "it's retrying" looks like the system doing its job. We've seen this exact shape: a reconnect loop that logged "reconnecting..." forever, healthy-looking, because it never stopped trying โ€” it just never tried the right address again.

Run it

node check.js --demo

Zero dependencies, no network โ€” models a DNS failover with a fake resolver that returns a dead IP for the first 3 lookups, then a live one, and runs a naive loop and a fixed loop against the identical scenario.

$ node check.js --demo Naive loop (resolve ONCE, reuse the IP for every retry): attempt 1: ip=203.0.113.10 FAIL attempt 2: ip=203.0.113.10 FAIL attempt 3: ip=203.0.113.10 FAIL attempt 4: ip=203.0.113.10 FAIL attempt 5: ip=203.0.113.10 FAIL attempt 6: ip=203.0.113.10 FAIL Fixed loop (re-resolve DNS on every attempt): attempt 1: ip=203.0.113.10 FAIL attempt 2: ip=203.0.113.10 FAIL attempt 3: ip=203.0.113.10 FAIL attempt 4: ip=203.0.113.20 OK

The naive loop runs out of attempts still failing against a dead IP that DNS stopped using three lookups ago. The fixed loop recovers the moment it asks again.

Against a real hostname (built-in dns module only, still zero deps):

node check.js --host chat.example.com [--n 5] [--interval-ms 1000]

This can't prove your own reconnect code is safe โ€” only reading that code can โ€” but it tells you whether DNS for that host is actually changing during the window you're testing, which is the precondition for this bug ever mattering.

The fix is a habit, not (only) code

Check your own system

Get the code