MongoDB Connection Timeout — Atlas, Firewall, and the 0.0.0.0/0 Trap

A server selection timeout means the driver found no reachable server: wrong URI, network egress blocked, or Atlas IP allowlist. The error text lists the attempted endpoints — that's the diagnosis.

What you'll see

Root causes

IP not in the Atlas allowlist (or it changed)

Atlas rejects at the network layer — which reads as a timeout, not auth. Home/CI IPs rotate: 0.0.0.0/0 is the tempting workaround and the security hole to avoid.

Wrong URI or firewall egress block

Typo in the host, a missing mongodb+srv:// (SRV record needed for Atlas), or the environment blocks outbound 27017. The error's attempted-endpoints list exposes all three.

Serverless/serverless-functions cold contexts

Serverless or function environments need the driver's serverless mode and have distinct egress rules; traditional connect strings behave inconsistently there.

Fix it

  1. Read the endpoints the driver actually tried
    # error text: [host1:27017, host2:27017] — compare against your Atlas cluster's hostname list
  2. Verify basic reachability from that environment
    nc -zv cluster0.xxxxx.mongodb.net 27017   # or curl -s https://cloud.mongodb.com/ping
  3. Add the exact source IP to the Atlas allowlist
    # Atlas console → Network Access → Add IP: your CI NAT IP or a dedicated egress IP; never 0.0.0.0/0 with username/password exposed
  4. Confirm the URI scheme
    # mongodb+srv://user:pass@cluster0.xxxxx.mongodb.net/db?retryWrites=true&w=majority   (srv for Atlas)

Field note

Timeout (network/allowlist) vs AuthenticationFailed (credential) vs bad-URI parse: the error family names the layer before you waste a debugging cycle on the wrong one. If you must allow broad access temporarily, pair 0.0.0.0/0 with short-lived rotated credentials and revert the allowlist the same day — public Atlas endpoints are scanned continuously.

Common questions

Why does it work from my laptop but not from the server?

Different egress IP: your laptop's IP is allowlisted, the server's isn't. Add the server's IP (or a static egress IP) — the timeout is Atlas dropping the handshake at the network layer.

How do I find the CI runner's IP for the allowlist?

Most CI providers publish ranges, or give static egress IPs on paid tiers. Alternatively run a job that curls an IP-echo service once, then allowlist that — remembering shared runners change.

Ship it right the first time

Our most-documented failures, packaged as ready-to-ship starter kits: Docker, Kubernetes, and Terraform.

Browse the template store →

One-time. Yours to modify. Instant download from the NinjaOps template store.