Skip to main content

Fly.io 18 Regions vs Render 5 vs Railway 4: A Multi-Region Exit Checklist for Leaving Edge Deployment for Owned Hardware

10 min readDora NodaDora Noda
Share
On this page

Eighteen regions sounds like a superpower until you check where your users actually are. Most teams running on Fly.io, Render, or Railway serve the overwhelming majority of their traffic from one or two continents — yet they pay edge prices, debug edge routing, and accept edge tradeoffs across a footprint they never needed. This post turns Techsy's July 2026 region matrix into an exit checklist: the region counts up front, then five steps that decide what you actually need and what to replace when you move to owned hardware.

Here is the matrix, re-checked against live docs on July 19, 2026:

PlatformRegionsRegion modelLatency story
Fly.io18Native multi-region, one commandSub-20ms from most populated areas
Render5 (Oregon, Ohio, Virginia, Frankfurt, Singapore)Each service pinned to one region100–200ms added for far users
Railway4 Metal (US West, US East, EU West, Singapore)Single region per service; multi-region not the focusSame single-origin penalty as Render
Owned Hetzner fleet6 locations (Falkenstein, Nuremberg, Helsinki, Ashburn, Hillsboro, Singapore)You pick 1–3; GeoDNS routesSame physics, a tenth of the bill

The checklist below walks through each row of that table as a decision: measure your latency budget, replace anycast routing, move the data layer, settle residency, re-price the fleet — and name the workloads where you should honestly stay on the edge.

Step 0: Measure your real latency budget before you move​

Nobody should leave 18 regions based on vibes. Pull your last 30 days of request logs or RUM data and bucket p50/p99 latency by user geography. You are looking for one of three shapes, and each dictates a different footprint:

  • Same-continent majority. If 90%+ of requests come from one continent, a single well-placed region plus a CDN covers you. A user 3,000 km from your origin sees roughly 60–100ms of extra round-trip time — noticeable, not fatal, and exactly the penalty Render and Railway users already accept on their single pinned region.
  • Two-hub split (e.g. US + EU). Two owned regions with latency-based routing gets every user onto the right continent. This matches what most "global" SaaS products actually need.
  • Genuinely global interactive. Sub-50ms everywhere, users on every continent hitting dynamic endpoints — this is the one shape where Fly.io's 18 regions earn their keep. See "When NOT to leave" below before going further.

The CDN carve-out matters more than any of these bullets: static assets, marketing pages, and cacheable API responses never needed 18 app regions. A CDN in front of one origin already serves that traffic from hundreds of edge pops. Only dynamic, uncacheable requests participate in your latency-budget decision — so measure those separately, or you will over-provision regions for traffic a CDN handles for free.

Step 1: Replace anycast with GeoDNS plus two or three owned regions​

Fly.io's signature trick is anycast: one IP announced from every region, with the network itself delivering each request to the nearest healthy Machine. It is genuinely good networking, and it is the single thing with no exact replacement on owned hardware. What you get instead is GeoDNS or latency-based routing — Route 53, Cloudflare Load Balancer, or any managed DNS with health checks — steering users to the nearest of your two or three regions.

You have todayOwned-hardware replacementWhat changes
Fly.io anycast across N regionsGeoDNS + 2–3 Hetzner locationsDNS-level steering (~seconds to fail over) instead of network-level (instant); one fewer "it just routes" guarantee to debug at 3am
Render single pinned region1:1 move to nearest Hetzner locationSame single-origin latency profile, minus the constraint that you can never change regions for an existing service
Railway single Metal region1:1 move (Metal maps cleanly: Virginia→Ashburn, Amsterdam→Falkenstein/Nuremberg, Singapore→Singapore)Same footprint, same latency, far lower bill

Two honest losses to budget for. First, deploys stop being one-command-global: you roll region by region behind your load balancer instead of fly deploy fanning out everywhere. For a two-region fleet this is a solved problem (staged rollout, health-gated promotion), not a research project. Second, per-request failover gets slower — DNS TTLs and health-check intervals measure in seconds, not milliseconds. If your availability math depends on sub-second cross-region failover for stateful traffic, that is a stay-on-edge signal, not a migration detail.

Step 2: Move the data layer deliberately — it was never multi-region anyway​

Here is the open secret of the region matrix: the app tier was global, but the data tier almost certainly was not. Check what you actually run:

  • Render managed Postgres (with PITR and replicas) lives in one region. Your replicas are high availability, not geo-distribution.
  • Railway Postgres is containerized, with highly-available Postgres still experimental since March 2026. Nobody has a globe-spanning Railway database.
  • Fly Postgres is the closest to genuinely multi-region — primary plus regional read replicas — with the fly-replay header routing writes back to the primary region. But note what that pattern admits: writes still travel to one region. The speed of light applies to Fly too.

So the owned-hardware mapping is refreshingly boring: run the primary in your biggest region, add read replicas in your second region if read latency justifies it, and keep the same write-goes-to-primary discipline you already had under fly-replay. Teams that dread operating Postgres can keep a managed database outside the fleet (the provider's region picker becomes your "multi-region" story for data, exactly as before) while the app tier moves to owned machines.

The one genuinely hard case is write-heavy global traffic — users on three continents all writing with single-digit-millisecond expectations. No checklist fixes physics: that workload needs either conflict-tolerant data modeling (CRDTs, regional sharding) or staying where the edge network already papers over the latency. Name it early if it is you.

Step 3: Settle data residency on purpose​

Residency is the rare migration step that gets easier instead of harder. On a PaaS, your residency proof is a region picker in a dashboard plus a subprocessor list. On owned hardware, it is a machine in a named building:

  • EU-only data → Falkenstein or Nuremberg (Hetzner-owned datacenters in Germany), Helsinki if you want a second EU zone.
  • US data → Ashburn (us-east) or Hillsboro (us-west).
  • APAC users → Singapore.

Hetzner's network zones reinforce the boundary for free: networks, load-balancer targets, and floating IPs stay inside one zone (eu-central, us-east, us-west, ap-southeast), so cross-border traffic happens only where you explicitly build it. For the audit file, "customer data lives on machines we rent in Falkenstein, network-zone eu-central" is a crisper sentence than any shared-responsibility paragraph. If you serve regulated customers, this step alone can justify the migration in a procurement review.

Step 4: Re-price the fleet honestly — compute plus egress​

Take a typical small production app — two web instances, one worker, one Postgres — and price it line by line. Compute first: a Hetzner CX22 (2 vCPU, 4 GB RAM) runs about €4/month and a CPX22 (3 AMD vCPUs, 4 GB) around €5–8/month, each with 20 TB of included traffic in EU locations. An equivalent always-on footprint on Fly.io starts near $2/month per small Machine but climbs per component (Machines + volumes at $0.15/GB/month + IPs), Render charges flat per-service tiers, and Railway meters usage per second.

Then price the line that actually decides the comparison: egress. Fly.io charges $0.02/GB in North America and Europe, $0.04/GB across Asia-Pacific, Oceania, and South America, and $0.12/GB in Africa and India. At 500 GB/month of NA/EU egress that is $10 — background noise. At 5 TB/month split across APAC, it is $200, more than the compute several times over. Hetzner's 20 TB inclusion swallows both scenarios without a second thought (US and Singapore locations include less, so check the location-specific quota if your origin sits there).

The sensitivity variable is egress volume and geography, full stop. Low-egress apps save modestly on compute; high-egress or APAC-heavy apps can save an order of magnitude. Run your own last-three-months bandwidth numbers through both pricings before committing — anyone quoting you a single "we cut the bill 80%" number without naming their egress profile is selling, not measuring.

When NOT to leave: the honest stay-on-edge list​

A checklist that only ever says "go" is a sales pitch. Stay where you are if any of these describe you:

  • Sub-50ms global interactive. Realtime collaboration, multiplayer, live bidding — anything where 100ms+ of intercontinental round trip degrades the product itself, not just a dashboard number. This is Fly.io's home turf: 18 regions with anycast is purpose-built for exactly this.
  • Sporadic traffic that lives on scale-to-zero. Internal tools, preview apps, and bursty workloads where Fly Machines' stop-on-idle (with 300ms–2s cold starts) beats paying for warm boxes. Owned hardware has no equivalent of billing zero for an idle night — your floor is the machine rental.
  • Zero ops capacity, honestly assessed. If there is nobody who will patch nodes, rotate certs, and answer the 3am page, the PaaS premium is buying something real. The migration math only works when the ops cost is headcount you already have, not heroics you hope for.

Techsy's graduation path — Railway while iterating, Render while growing, Fly.io when scaling globally — gets one more rung under this framing: owned hardware when your footprint, residency, and egress math say the edge premium stopped buying you anything. Each move has a trigger; "we assume we need 18 regions" was never one.

The one-page exit checklist​

  1. Bucket p50/p99 latency by user geography; separate cacheable from dynamic traffic.
  2. Classify your shape: one continent, two hubs, or genuinely global interactive.
  3. If global-interactive or sporadic scale-to-zero dominates, stop — stay on the edge.
  4. Map each current region to 1–3 owned locations (Virginia→Ashburn, Amsterdam→Falkenstein/Nuremberg, Singapore→Singapore).
  5. Stand up GeoDNS/latency-based routing with health checks; accept seconds-scale failover.
  6. Move the database as primary-plus-replicas (or keep managed DB external); preserve write-to-primary discipline.
  7. Pin residency per dataset to a named location and network zone; write the audit sentence.
  8. Re-price with your own egress volume and geography — not a headline percentage.
  9. Plan staged region-by-region deploys to replace one-command-global.
  10. Schedule the ops on-call rotation before cutover, not after.

Leaving the edge is not a statement about edge platforms — they win the workloads they were built for. It is a statement about knowing which workload you actually run. Measure first, and the region count picks itself.

Bex.co is the open-source, AI-native Render alternative — push a git repo, get a running HTTPS service on machines you own. Star the repo on GitHub or deploy your first app today.

Related articles

Check your move before you migrate

Free browser tools: check a render.yaml or your Render scripts against bex, or turn a Heroku app or docker-compose.yml into a draft render.yaml. Nothing you paste leaves your browser.

Open the migration tools