Skip to main content

Static Outbound IPs Are a Paid Add-On on PaaS and a Free Property of Your Own Server

16 min readDora NodaDora Noda
Share

Your app's outbound IP is not yours until something outside your PaaS asks what it is. The moment a partner bank says "allowlist the IPs that will hit our API," or an SMTP relay says "we only accept mail from known senders," or a database firewall says "add your source address to the security group" — your PaaS's egress identity stops being an implementation detail and becomes a production dependency. On most platforms that dependency has been dynamic, pooled, and undocumented by design.

Railway's July 3, 2026 changelog finally gave that dependency a first-class control plane: static outbound IPs and first-class IPv6 toggling, both manageable from the dashboard and now from the CLI. It is a real improvement — and it makes visible a pricing question that self-hosted teams never had to ask, because a server you own has had a fixed egress address since the day it was provisioned.

This post is the allowlist tax, shown line by line: what Railway shipped, what it costs, what the same allowlist workflow costs on hardware you own, and the caveats the changelog headline does not include.

The Tax in One Table

Before the mechanics, the economics. Pick the egress identity you need, read across:

Egress setupWhat you getHow you turn it onMonthly cost for the IP itselfAllowlist workflow
Railway, no static IPsPooled, dynamic egress shared across the platformDefault — nothing to doIncluded (no line item)You cannot allowlist — source address rotates
Railway, static outbound IPs3 shared IPv4s, load-balanced, high-availability per service, region-specificDashboard: Service → Settings → Networking → Enable Static IPs → Redeploy; CLI: railway outbound-network static-ip enable → redeployIncluded with Pro plan ($20/month/workspace, includes $20 usage credits) — no per-IP surcharge listed, but Pro is requiredAdd 3 IPs to every external allowlist; updates take effect on next deploy
Heroku without FixieDynamic, unpredictable Heroku dyno egressDefaultIncludedNeeds a proxy — source IP cannot be pinned
Heroku with Fixie2 static IPs via outbound proxy (SOCKS/HTTP CONNECT tunnel)heroku addons:add fixie, set FIXIE_URL as proxyAdd-on metered by requests + transfer (plan-dependent, separate from dyno bill)Add 2 proxy IPs to allowlist; app must proxy outbound HTTP through FIXIE_URL
Hetzner Cloud server1 dedicated Primary IPv4, 1 Primary IPv6 per server, fixed for the server's lifetimeAuto-assigned on create (or add a Primary IP after)IPv4: €0.50/month, IPv6: free — on top of the server itself (e.g., CX22 from ~€4–5/mo, 20TB inclusive traffic)Add 1 IP to allowlist; stays until you delete or move the server
Hetzner dedicated / bare metal1 static IPv4 included with the server, fixed, exclusive to youAssigned at provision, stays with the machineIncluded with the server — the IP is a property of the hardware you rent, not a feature toggleAdd 1 IP to allowlist; no shared-pool caveat

Two things jump out before any prose does.

First, on PaaS, a fixed egress identity is an upgraded tier or an add-on proxy — gated behind a Pro workspace, or billed as a separate add-on with its own meter. On hardware you own, it is a property of the machine: a Hetzner Cloud server gets a Primary IP for half a euro, a dedicated server includes one at no extra line item, and the address is yours exclusively for as long as you keep the box.

Second, the cardinality matters. Railway gives you three shared IPs (up from one, with automatic HA migration after July 13, 2026). Heroku via Fixie gives you two. Your own box gives you one exclusive IP. If an external party charges per IP allowlisted, limits the number of entries, or manually vets each one, that cardinality is not trivia — it is operational overhead. Every region change, every new environment, every new service multiplies the entries.

The rest of this post fills in how each cell got that way.

What Railway Actually Shipped on July 3, 2026

The changelog entry is titled "The peaceful way to ship software, static outbound IPs and IPv6 in the CLI" — the headline buries the lede. The networking changes are:

A CLI group where there was only a dashboard toggle before. railway outbound-network now mirrors the dashboard's egress switches so humans and agents can script them:

  • railway outbound-network status — summarizes fixed egress IPv4s and IPv6 state for the selected service/environment, including whether the allocation is high-availability.
  • railway outbound-network static-ip enable / disable — stages a service-level change; takes effect on the next deploy, not immediately.
  • railway outbound-network ipv6 enable / disable — stages an environment-level IPv6 toggle; also requires a deploy to apply.

All commands accept --service, --environment, --project, and --json selectors, and the JSON output includes a lifecycle field telling automation whether the change was immediate or staged. To use them you need a current CLI (railway upgrade) and railway outbound-network --help.

Three high-availability IPs instead of one. The old static-IP setup assigned a single address per service. The new default load-balances egress over three IPv4s per region for throughput and resiliency. Existing single-IP services can opt into HA via an "Enable HA Static IP" switch — you then review the new trio, update every external allowlist, and redeploy. Services that do not act by July 13, 2026 are migrated automatically, which is a concrete deadline to put in your calendar if you have any allowlists in the wild.

Pro-only, per-service, region-tied, outbound-only. From the docs: static outbound IPs are available to customers on the Pro plan ($20/month per workspace, seats unlimited, $20 of usage credits included). They are per-service and region-specific — move a service to another region and the addresses change. They handle outbound connections from all instances of that service, load-balanced across the three IPs, and cannot be used for inbound traffic. A subtle but load-bearing line in the docs: the addresses may be shared across customers, not exclusive — you are renting a stable share of a pool, not a dedicated IP.

IPv6 is a parallel toggle at the environment level (not per-service like static IPv4), also staged-then-deployed. The docs and changelog list no per-IP surcharge beyond the Pro-workspace gate, and no egress transfer premium tied to the feature — you pay the platform's normal compute + volume + egress rates either way.

If you have never needed an allowlist, this all reads like plumbing. If you have, it reads like the first time someone wrote down the price of a thing you were previously told not to think about.

Why Allowlists Make Egress Identity a Production Dependency

Dynamic egress is fine until a third party makes it your problem. Four scenarios where it reliably does:

1. Banking and fintech APIs. Payment processors, open-banking gateways, and treasury platforms frequently gate API access behind source-IP allowlists. A mid-size SaaS that pulls settlement files over SFTP or posts disbursements to a partner API will be given a form that says "list the egress IPs we should allow." On pooled dynamic egress, the honest answer is "we cannot" — so you open a ticket with your PaaS vendor, learn about static IPs or a proxy add-on, and then open a second ticket with the bank to register the new addresses, wait for their change window, and coordinate the redeploy that activates them.

2. Corporate-firewalled databases. Plenty of production Postgres, MySQL, and MSSQL instances still sit behind a firewall that allows only known client IPs. Railway's own docs use this as the canonical example: "database services" hosted elsewhere that filter by source address. The workaround without a fixed IP is either "open the firewall to 0.0.0.0/0" (audit will love that) or run a jump host / VPN — which is just building the fixed-egress property yourself, badly.

3. SMTP relays and email deliverability. Many transactional email relays and corporate mail gateways still score senders partly on IP reputation and allowlist membership. If your app sends mail directly or through a relay that filters on source IP, rotating egress means your reputation is smeared across a shared pool. Railway's docs explicitly call out the symptom: when a partner filters by source address, pooled egress is the wrong answer.

4. Partner SaaS APIs and WAFs. The everyday version: a partner's WAF (Cloudflare, Akamai, AWS WAF) is configured to allow only clients from a known set of IPs, or their API docs say "we require IP allowlisting for server-to-server calls." Your app works in staging (where the partner disabled the check), fails in production on the first call, and the error message is an opaque 403 with no hint that it is an IP problem. Debugging time is measured in Slack threads, not minutes.

The pattern is the same every time: a third party turns your outbound address into a credential, and a platform with dynamic egress turns that credential into one you cannot present on demand. That is the allowlist problem, and it is why static egress went from "nice to have" to "will block a launch" — which is exactly when vendors can price it.

What That Same IP Costs on Hardware You Own

Now price the same credential on a machine you own outright via a provider like Hetzner. The arithmetic is deliberately boring:

Hetzner Cloud — the lab test. Cloud servers do not include a public IP by default, but adding one is explicit and cheap: one Primary IPv4 per server at €0.50/month, one Primary IPv6 free, added at server create or afterward. A CX22 (2 vCPU, 4GB RAM) lands in the €4–5/month range depending on region, with 20TB of inclusive traffic on the cheapest cloud tier and private networks between your nodes at no extra private-transfer premium. Your service's egress IP is the server's Primary IP — single, exclusive, stable for the server's lifetime, and visible in the console from the moment the machine exists. To allowlist it, you copy one address into one form, once.

Hetzner dedicated / bare metal — the "it just comes with an IP" tier. A dedicated server (AX, EX, or the GPU line up to the €889/month RTX PRO 6000 Blackwell if you are self-hosting inference) includes a static IPv4 as a property of the hardware. There is no "Enable Static IPs" toggle, no redeploy to activate it, no shared-pool footnote. The IP is yours exclusively while you keep the server. If you run a Kubernetes fleet on those boxes via Cluster API — which is how self-hosted PaaS fleets typically provision them — every node has that same property, and your egress IPs are just your nodes' IPs behind whatever egress gateway or NAT gateway you run.

The cost comparison, stripped of narrative:

  • Railway path for one service needing allowlists: Pro workspace $20/month (seats unlimited, $20 credits included) + static IPs included in Pro (no separate line item) + 3 IPs to register per region + redeploy to activate + shared-pool caveat. Add $0 if you were already on Pro for other reasons; add $20/month if the allowlist is the reason you upgraded.
  • Heroku path via proxy: Dyno bill unchanged + Fixie add-on (request-count and transfer-metered, plan-tiered, paid separately from dyno usage) + app code must proxy outbound HTTP via FIXIE_URL + 2 IPs to register.
  • Hetzner Cloud path: Server cost + €0.50/month IPv4 (IPv6 free) + 1 exclusive IP to register, no activation deploy, no plan gate.
  • Dedicated server path: Server cost, IP included, 1 exclusive IP to register, again no toggle.

No one picks infrastructure on a single €0.50 line. The point is structural: on PaaS, egress identity is a feature you enable, behind a plan you pay for, producing a shared resource you then go register with every partner. On hardware you own, egress identity is a property of the server you already provisioned, producing an exclusive resource that exists whether or not you ever file an allowlist form. The allowlist tax is not the euro amount — it is the workflow that the platform's defaults impose.

That tax compounds per service and per region. Railway's IPs are per-service and per-region. A fleet with a web service, a worker, and a webhook handler — three services in us-east and a replica in eu-west — is registering 12 → 18 IPs after the HA upgrade (3 per service per region), across multiple allowlist tickets. The same fleet on dedicated hardware behind a single egress gateway (a NAT instance, a cloud NAT, or a egress-gateway Deployment) registers one IP for all of it.

The Caveats the Headline Does Not Include

Railway's feature is genuinely useful, and these caveats are not footnotes — they are the difference between "we solved allowlists" and "we made them manageable":

Shared, not exclusive. The docs state the addresses might be shared across customers. For most allowlists that does not matter — the IP is still static and will be allowed. For IP-reputation-sensitive flows (email sending, rate-limited partner APIs that treat a shared IP's traffic as one client), sharing means your reputation is pooled with strangers. Your own server's IP is exclusive; abuse by a neighbor cannot get your allowlisted address block-holed.

Per-service, per-region, outbound-only. Each service gets its own trio, each region its own allocation, and the addresses cannot receive inbound traffic. If you assumed "static IP" meant "stable ingress address for webhooks," it does not — that is a different PaaS feature (custom domains with stable DNS). Mix the two up and your allowlist will be correct but your webhook receiver will still be on dynamic ingress.

Migration deadline with external side effects. Services on the old single-IP setup that do not enable HA themselves will be moved automatically after July 13, 2026 to three new addresses. That is correctly flagged as high-availability, but any external allowlist still pointing at the old single IP will need to be updated to the new trio before the migration, or it will break on the cutoff. Railway surfaces the new addresses in the dashboard for this reason — treat the migration like a credential rotation, not a background upgrade.

Moving a service moves its identity. Relocate a service to another region and the static IPs change. For teams that routinely shift workloads between regions, the allowlist is now a region-pinned artifact. On hardware you own, moving a workload between nodes behind the same egress gateway keeps the same outbound IP; moving it to a new region behind a new gateway is an explicit decision to present a new address.

IPv6 is there, the internet is not uniformly. Outbound IPv6 is a welcome addition — it future-proofs egress as IPv6 adoption climbs past 40% globally — but many corporate firewalls, bank VPNs, and SMTP relays still filter or simply do not accept IPv6 allowlist entries. Some partners will say "IPv4 only" on the form. The presence of an IPv6 toggle does not halve your IPv4 allowlist work.

CLI control is staged, not instant. Both static-ip enable and ipv6 enable require a redeploy to take effect and report staged via the lifecycle JSON field. Automation that scripts enable && curl partner will race the deploy. The safe pattern is enable → check status --json → wait for deployed state → then tell the partner to expect the new IPs.

None of these is a dealbreaker. All of them are the kind of thing that turns a launch-night "just allowlist us" Slack message from a five-minute fix into a coordinated deploy across two companies' change windows. Teams that have lived through that coordination tend to develop a strong preference for a single, exclusive, long-lived egress IP they control directly.

When to Pay the Tax, When to Own the Machine

This is not an argument that managed PaaS is wrong — it is an argument that egress identity should be priced into the platform choice before a partner makes it urgent.

Pay the PaaS tax when:

  • You have one or two services, one region, and partners that accept three allowlist entries without per-IP vetting — the Pro-workspace gate is cheaper than operating your own fleet.
  • Your team has no one who wants to own egress gateways, NAT, or node networking — the $20/workspace + redeploy workflow is an honest trade for not thinking about subnets.
  • Your workload genuinely needs platform features (instant preview deploys, git-push with buildpacks, autoscaling past zero) more than it needs network ownership.

Own the machine when:

  • You are allowlisting across many services or regions and the per-service IP multiplication is the real cost — not the euros, the coordination overhead with every partner.
  • A partner limits the number of allowlisted entries, charges per entry, or manually vets each IP — one exclusive IP behind a gateway beats three shared ones per service.
  • You already run dedicated or cloud hardware for cost reasons (the 2026 Hetzner repricing coverage on this blog's own list makes that math easy to revisit) — the egress property comes free with sunk hardware.
  • You need IP reputation isolation (email, rate-sensitive APIs) — exclusive beats shared.

If you are on the fence, the cheapest hedge is boring: ask every integration partner, in writing, before you build, what they require for source-IP allowlisting — number of entries allowed, how long a change takes, whether IPv6 is accepted, and whether shared IPs are acceptable. The answer frequently decides the infrastructure shape more reliably than any pricing-page comparison.


Self-hosting does not make egress identity a feature — it makes it a side effect of already owning a machine with an address. Bex.co is the open-source, AI-native Render alternative that leans into that property: push a git repo, get a running HTTPS service on machines you own, where the outbound IP is your server's IP and not a line item. The platform is Apache-2.0, the hardware is yours, and the allowlist form has one line. Star the repo on GitHub.


Sources

Related articles

Run this on infrastructure you own

bex is the open-source, AI-native Render alternative — push a git repo and get a running HTTPS service on your own machines.

Get started with bex