Fly.io gives your apps IP addresses so they can be reached from the internet. When you deploy an app, Fly automatically assigns a public IPv4 address, and if you’re using IPv6, it assigns one of those too. You can see these IPs in your app’s dashboard or by running flyctl ips list.

Here’s an app running with both IPv4 and IPv6 addresses:

$ flyctl ips list --app my-cool-app
TYPE      ADDRESS            CREATED
v4        172.123.45.67      2023-10-27T10:00:00Z
v6        2a00:1450:4007:800::1000 2023-10-27T10:00:00Z

You can also allocate additional IP addresses to an app. This is useful if you need a dedicated IP for a specific service, or if you want to rotate IPs for some reason. To allocate a new IP, you use the flyctl ips allocate command. For example, to allocate a new IPv4 address:

$ flyctl ips allocate --app my-cool-app --region lhr
TYPE      ADDRESS            CREATED
v4        172.123.45.68      2023-10-27T10:05:00Z

This command allocates a new IPv4 address in the London (lhr) region. You can specify --region to choose where the IP is allocated. If you omit --region, Fly will pick a region for you. You can also allocate IPv6 addresses using the same command:

$ flyctl ips allocate --app my-cool-app --region fra --ipv6
TYPE      ADDRESS            CREATED
v6        2a00:1450:4007:801::2000 2023-10-27T10:10:00Z

These newly allocated IPs are immediately available and can be used by your application. Fly.io uses a global Anycast network, so these IPs are accessible from anywhere in the world.

Managing IPs is done via flyctl ips. You can list them with flyctl ips list, allocate new ones with flyctl ips allocate, and remove them with flyctl ips release. For example, to release the IPv4 address we just allocated:

$ flyctl ips release --app my-cool-app 172.123.45.68
Successfully released IP address 172.123.45.68

It’s important to note that the first IP address allocated to an app cannot be released as long as the app exists. This is your primary IP. You can only release IPs that you’ve explicitly allocated after the initial one.

When you scale your application, Fly.io doesn’t automatically assign new IP addresses to each new instance. Instead, all instances of your application share the same IP addresses. Traffic hitting those IPs is routed to healthy instances of your app via Fly’s load balancer. This is why you typically only need a few IP addresses per app, even if you have many running instances.

The IP addresses are associated with your Fly organization, not just a single app. This means if you have multiple apps within the same organization, you can allocate IPs to one app and potentially use them for another if your routing configuration allows it (though typically, IPs are tied to a specific app’s routing). The flyctl ips commands are scoped to the --app flag, making it clear which app the IP is being managed for.

One key aspect of Fly.io’s IP management is that you can’t directly "assign" an IP to a specific instance of your application. Fly’s routing layer handles directing traffic. If you need to bind to a specific IP address within your application code, you’ll need to configure your application to listen on that IP address. For most web applications, listening on 0.0.0.0 or :: is sufficient, as Fly’s proxy will handle the external IP to internal port mapping.

The IP addresses you allocate are static and persistent for the life of the allocation. They won’t change unless you explicitly release them. This is crucial for services that rely on stable IP addresses, like DNS records or whitelisting.

If you’re running services that require multiple public IPs for different virtual hosts or distinct services behind the same app deployment, allocating additional IPs is the way to go. You can then configure your web server (like Nginx or Caddy) within your Dockerfile or application code to respond to requests coming in on specific IP addresses.

The underlying infrastructure uses a global load balancer. When a request hits one of your allocated IP addresses, it enters Fly’s network and is then directed to the nearest healthy instance of your application. This is why you see low latency globally. The IP address itself is just the entry point into this sophisticated routing system.

You can also manage IP addresses via the Fly.io API, which is useful for automation and integration with CI/CD pipelines. The API endpoints for IP management mirror the functionality of flyctl ips.

You can have up to 100 IP addresses per organization. If you hit this limit and need more, you’ll need to contact Fly.io support.

The default IP allocation strategy is to provide a single IPv4 address. If you intend to use IPv6, you must explicitly allocate an IPv6 address using the --ipv6 flag. Fly.io encourages the use of IPv6, and it’s generally more available and cost-effective.

If you want to remove an IP address, you use flyctl ips release. Be careful, as this is permanent. Once released, the IP address is gone and cannot be recovered. You would need to allocate a new one if needed. The command requires the specific IP address you wish to release.

The next thing you’ll likely need to understand is how to configure your application to use these IPs, especially if you’re running multiple services or need specific routing within your app.

Want structured learning?

Take the full Fly-io course →