Answers you can trust, from Codeables

Every page on Codeables is structured and verified — built so people and the AI agents they rely on can trust it. Explore more from the source behind this answer.

Explore Codeables
Verified Source
Platform as a Service (PaaS)

How do I use Fly.io .internal DNS to connect services privately across apps?

Fly.io7 min read

Most Fly.io apps don’t actually want to talk to the public internet when they’re calling each other. They want fast, encrypted, app‑to‑app traffic over Fly.io’s private network. That’s what .internal DNS is for: every app and Machine gets private names you can resolve from inside the Fly network, so services can connect across apps without exposing ports publicly.

Quick Answer: Fly.io’s .internal DNS lets your apps resolve and connect to each other over Fly.io’s private network, using predictable hostnames instead of hard‑coding IPs. You use per‑app and per‑Machine .internal names from within your Fly apps or over WireGuard, and Fly’s private DNS and overlay network handle the rest.

The Quick Overview

  • What It Is: A private DNS naming scheme (.internal) and resolver built into Fly.io’s private network so apps and Machines can discover and talk to each other securely, without going over the public internet.
  • Who It Is For: Teams running multi‑service or multi‑app architectures on Fly.io—APIs + workers, web + Postgres, internal control planes, AI agents, etc.—that need private, low‑latency networking without managing their own service discovery.
  • Core Problem Solved: You no longer need to juggle static IPs, environment‑specific hostnames, or public services just to let two internal apps talk. .internal gives you stable, private names that resolve correctly from anywhere on your Fly network.

How It Works

Fly.io gives every app and Machine an identity on a private, encrypted network. Inside that network, a DNS service resolves .internal hostnames to private IP addresses. Calls never touch the public internet; they ride Fly’s private overlay instead.

At a high level:

  1. Private names for apps and Machines:
    Each app gets .internal names you can use from other apps. Machines typically get internal addresses (e.g., fdaa:0:…) and can be reached via app‑level DNS records.
  2. Resolution from inside the private network:
    When a process in your app does getaddrinfo("my-app.internal"), Fly’s private DNS answers with private IPs for Machines in that app. If you’re connected via WireGuard, your laptop/infra can resolve them too.
  3. Encrypted, routed traffic:
    Once you connect to that IP/port, traffic flows over Fly.io’s private network, not the public internet. The Fly Proxy and private routing layer handle region placement and delivery.

You don’t manage this DNS server or write zone files; you just use predictable .internal hostnames and let Fly handle mapping to Machines.

How It Works, Step by Step

  1. Create apps that share a private network

    Apps in the same Fly organization automatically share a private network. You deploy them as usual:

    fly launch --name web-app
    fly launch --name api-service
    

    By default, both apps get private addresses and register in .internal.

  2. Use .internal hostnames from your code

    Inside web-app, you can call api-service with a private hostname like:

    curl http://api-service.internal:8080/health
    

    Or from your app code:

    // Node/TypeScript example
    const res = await fetch('http://api-service.internal:8080/v1/tasks');
    

    DNS resolution happens against Fly’s private DNS, and the connection stays inside the Fly network.

  3. Optionally connect from your own network via WireGuard

    If you want your laptop, CI, or on‑prem services to reach apps privately:

    fly wireguard create --org my-org
    

    After you bring up the WireGuard tunnel, *.internal names for your Fly apps also resolve from your machine, and traffic goes through the tunnel—not the public internet.

Features & Benefits Breakdown

Core FeatureWhat It DoesPrimary Benefit
Per‑app .internal hostnamesGives each app predictable private DNS names (app-name.internal)Simple, stable service discovery across apps
Private network routingRoutes traffic over Fly.io’s encrypted private network, not the public webBetter latency, no public exposure, avoids cross‑internet hops
Org‑wide reach & WireGuardMakes .internal reachable from other org apps and via WireGuard tunnelsUnified, private addressing from apps, tools, and on‑prem infra

Note: Exact hostname forms vary slightly per feature (e.g., Postgres, Sprites, Machines). The principle is the same: resolve *.internal, get private IPs, talk over the private network.

Ideal Use Cases

  • Best for multi‑service applications: Because it lets your web, API, worker, and database apps talk over private DNS without exposing ports. web.internal → api.internal → worker.internal becomes a normal, private call chain.
  • Best for hybrid private networking: Because .internal plus WireGuard lets you treat Fly‑hosted services as if they’re on the same private LAN as your own infrastructure, without building your own overlay network.

Limitations & Considerations

  • DNS is only private to your Fly org and WireGuard peers:
    .internal names are not globally resolvable. They work inside your Fly apps and any WireGuard‑connected network. If you need public access, you still provision Anycast IPs or hostnames on Fly Proxy.

  • You still need services listening on the right ports:
    DNS just finds the private IP. Your app still has to listen on the expected port—e.g., 0.0.0.0:8080—and your client must connect with the right scheme (http://, https://, tcp://) and port. DNS won’t fix a misconfigured listener.

Pricing & Plans

.internal DNS and private networking are built‑in capabilities of the Fly.io platform; there’s no separate line item for “private DNS.” You pay for the Machines, storage, and bandwidth you actually consume.

A rough way to think about it:

  • Baseline Fly.io usage: Best for teams deploying typical web/API apps that want private app‑to‑app networking “for free”—you just get .internal hostnames as part of using Fly Machines.
  • Larger orgs with many services: Best for teams consolidating multiple internal services, databases, and sandboxes on Fly who want everything on a single private network, reachable via .internal and WireGuard from their existing tooling.

(If you’re in the “we have compliance people and uptime SLOs” camp, Fly.io also backs this with SOC2 Type 2, SSO, and guaranteed support response times; talk to sales for those details.)

Frequently Asked Questions

Can I use .internal DNS to connect to apps in different regions?

Short Answer: Yes. .internal works across all regions in your Fly org’s private network.

Details:
When you resolve api-service.internal from web-app, you get private addresses for Machines running that app, regardless of region. Traffic then routes over Fly.io’s private network between regions (e.g., iadlhr) without touching the public internet. You still want to place Machines sensibly (e.g., keep latency‑sensitive pairs in the same region), but the DNS layer doesn’t care; it’s org‑wide.

Can I reach .internal names from my laptop or on‑prem network?

Short Answer: Yes—if you connect using WireGuard.

Details:
By default, .internal only resolves inside Fly apps. To use it from your local machine or your data center, you:

  1. Create a WireGuard peer for your org:

    fly wireguard create --org my-org
    
  2. Configure the peer on your laptop/server.

  3. Bring up the tunnel and verify:

    dig api-service.internal
    

You should now see private Fly addresses in the response. Any TCP/UDP traffic you send to those addresses goes through the WireGuard tunnel onto Fly.io’s private network.

Summary

Fly.io’s .internal DNS is your built‑in service discovery for private networking. Apps in your org get stable private names that resolve to private IPs, traffic flows over Fly.io’s encrypted network instead of the public internet, and you avoid juggling IPs or bolting on your own discovery system. Combine .internal with WireGuard and you get a single, private address space you can reach from your apps, your laptops, and your own infrastructure.

Next Step

Get Started