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)

Fly.io vs Google Cloud Run: which is better for long-lived services, websockets, and private networking?

Fly.io14 min read

Most teams hit the same wall with Google Cloud Run the moment they move past simple HTTP APIs: you need long‑lived connections, predictable networking, and something better than “hope the autoscaler keeps my instance alive.” That’s where Fly.io starts to look less like “another place to run containers” and more like a different compute model built for this exact mess.

Quick Answer: For long‑lived services, WebSockets, and private networking, Fly.io’s Fly Machines and private WireGuard‑backed network usually beat Cloud Run’s request/timeout‑centric model. Cloud Run is great for short‑lived stateless HTTP, but its constraints make real‑time connections and network‑heavy systems harder and more fragile.


The Quick Overview

  • What It Is:
    A comparison of Fly.io’s Machine‑based platform vs Google Cloud Run’s managed container service, focused specifically on long‑lived services, WebSockets, and private networking.

  • Who It Is For:
    Developers and platform teams deciding where to run real‑time apps, persistent services, or internal APIs that need private networking and fewer “why did my instance disappear?” surprises.

  • Core Problem Solved:
    Choosing the right platform so your app can keep connections open, talk privately to other services/databases, and scale globally without Kubernetes or DIY networking.


How the Two Platforms Think About Compute

Before we get to WebSockets and private networking, it helps to understand the mental model of each platform.

  • Fly.io:
    Runs everything on Fly Machines: hardware‑virtualized containers that start fast enough to handle HTTP requests, can be long‑lived, and scale into tens of thousands of instances. You get private networking by default, Anycast routing via Fly Proxy, and optional “serverless‑like” behavior (scale‑to‑zero, per‑request Machines) without hiding the VM underneath.

  • Google Cloud Run:
    Runs OCI containers in a managed environment on top of Knative. It’s request‑driven: concurrency and max instance counts drive autoscaling, and timeouts define how long a request is allowed to run. It’s excellent for stateless HTTP workloads and simple background jobs, less happy when your app wants to hold open connections for a long time or control networking like a grown‑up.

Both run containers. The big differences are:

  • Lifecycle: Machines behave like VMs you control; Cloud Run instances behave like request processors the control plane owns.
  • Networking: Fly gives you a flat private network plus public Anycast; Cloud Run hangs off Google’s VPC with more configuration and more “this feature only works in region X” caveats.
  • Fit for long‑lived connections: Fly Machines don’t care if your socket is open for hours; Cloud Run fundamentally does.

Long‑Lived Services: Who Actually Likes Keeping Things Running?

“Long‑lived” here means more than just no scale‑to‑zero — we’re talking:

  • Persistent TCP connections (e.g., message brokers, custom RPC)
  • Stateful workers that keep in‑memory state or caches
  • Services that must not be killed mid‑session because an autoscaler got bored

Fly.io: Machines as Long‑Lived Processes

On Fly.io, a Machine is effectively your long‑lived process:

  • You can run them 24/7 or scale to zero when idle.
  • Start times are fast enough that you can treat new Machines like forking processes.
  • You decide when to update, stop, or restart them (rolling deployments, blue‑green, etc.).
  • There’s no hard “your request took too long, we’re killing the instance” deadline from the platform.

Concrete behaviors:

  • You can run a long‑lived worker that keeps a connection to Postgres, Redis, or anything else for days.
  • You can attach local NVMe and keep hot data next to the process.
  • If you want “serverless‑ish,” you can still scale Machines based on load, but the compute primitive doesn’t change.

Operationally, this feels closer to running VMs than to a “functions” service, but you still get:

fly launch
fly deploy
fly scale count 3

not “figure out which YAML is secretly controlling your life.”

Cloud Run: Long‑Lived Only If You Squint

Cloud Run instances are meant to:

  • Spin up to handle requests.
  • Serve them within a max request timeout (configurable, but still a hard cap).
  • Scale down to zero when idle.

You can have instances that effectively stay warm for a while, but:

  • The platform is free to kill idle instances at any time.
  • You’re at the mercy of timeouts for individual requests.
  • Long‑running background work usually gets pushed into Cloud Run Jobs, Cloud Functions, or GCE/GKE.

If you try to treat Cloud Run like an app server that should “just stay up,” you’re fighting the grain:

  • In‑memory session state is fragile.
  • Anything that’s not a relatively quick HTTP/gRPC request can be terminated based on timeout rules.
  • You end up bolting on more infrastructure (GKE, GCE, Pub/Sub) once things get complicated.

Verdict for long‑lived services:
If your mental model is “this process should be up and reachable like a VM, but I don’t want to manage the VM,” Fly.io is a better fit. Cloud Run is happier as a stateless request grinder.


WebSockets and Real‑Time Connections

WebSockets, SSE (Server‑Sent Events), and other long‑lived HTTP connections are where the “serverless” façade really starts to crack.

WebSockets on Fly.io

Fly Machines behave like regular Linux processes behind Fly Proxy. That means:

  • WebSockets just work: no special mode, no weird timeouts beyond what you set.
  • Fly Proxy terminates TLS, speaks HTTP/1.1 or HTTP/2, and correctly handles WebSocket upgrades.
  • Because Machines can be long‑lived, keeping a WebSocket open for hours is normal, not a trick.

You can also:

  • Place Machines in regions close to users (iad, lhr, syd, etc.) for lower WebSocket latency.
  • Use private networking to talk to backends (like Postgres or other services) without leaving Fly’s network.

Basic example in fly.toml:

[http_service]
  internal_port = 8080
  force_https = true
  auto_stop_machines = "off"
  auto_start_machines = true

Your app listens on :8080, handles Upgrade: websocket requests, and Fly Proxy keeps connections routed to the right Machine.

WebSockets on Google Cloud Run

Cloud Run supports HTTP/1 and HTTP/2, but WebSockets are bounded by:

  • Request timeout limits — WebSocket connections are still “requests” from the platform’s perspective.
  • Idle connection behavior — instances can be killed if they’re idle except for a few long‑lived connections.
  • Load balancing and scaling semantics that don’t prioritize “keep this particular connection on this instance forever.”

You can run WebSockets on Cloud Run in simple cases, but:

  • It’s easy to hit weird edge behaviors with timeouts, restarts, or autoscale events dropping connections.
  • For serious real‑time systems (chat, games, collaborative editors), people often glue on more infra (e.g., GKE, custom NGINX/Envoy gateways, or third‑party WebSocket services).

Verdict for WebSockets/real‑time:
Fly.io is designed so “keep a TCP connection open for as long as you need” is normal. On Cloud Run, it’s always working against a timeout‑driven, request‑centric design.


Private Networking and Internal Services

Here’s where the platforms diverge hard.

Private Networking on Fly.io

Every Fly app lives on a private, encrypted network:

  • You get a /24 private IPv6 and IPv4 space per organization (under the hood) with WireGuard‑based encryption.
  • Machines can talk to each other privately across regions without crossing the public internet.
  • You can connect this Fly private network to your own infrastructure using WireGuard.

Practical outcomes:

  • Run a public API app and a private Postgres cluster (or any internal service) and let them communicate over Fly’s private network. No public IPs needed.
  • Multi‑region internal services still communicate over private links.
  • You can open a WireGuard tunnel from your laptop or datacenter into the same network and talk to Machines like they’re in your LAN.

This is not “we gave you a VPC and a 200‑page networking guide.” It’s:

fly wireguard create

and now you have a secure tunnel to your private network.

Private Networking on Google Cloud Run

Cloud Run lives inside Google Cloud’s world:

  • It can connect to a VPC using Serverless VPC Access or similar features.
  • You can reach internal services in that VPC and other Google Cloud resources privately.
  • You’ll manage IAM, firewall rules, and networking configs across multiple services.

This is powerful, but also:

  • More moving parts: VPC connectors, egress rules, NAT, and per‑region configuration.
  • Less straightforward if you want simple, per‑app private networking that just spans regions.
  • Not as direct for connecting your external infrastructure (on‑prem, another cloud) into the same private network without getting into VPN/VPC peering territory.

Verdict for private networking:
If you want a flat, encrypted private network where all your apps and databases can talk without touching the public internet (plus simple WireGuard into your infra), Fly.io is purpose‑built. If you’re already deeply invested in Google Cloud VPCs and don’t mind networking plumbing, Cloud Run can fit into that world but won’t simplify it.


Feature‑by‑Feature Breakdown

Area / FeatureFly.io (Fly Machines & private network)Google Cloud Run
Compute modelLong‑lived Machines that can also scale to zero; hardware‑virtualized containers with fast startupRequest‑driven container instances managed by Knative; optimized for stateless HTTP
Long‑lived servicesFirst‑class; Machines can run indefinitely without platform‑enforced request timeoutsPossible, but constrained by request timeouts and autoscaler behavior
WebSockets / SSE / long HTTPSupported naturally; connections can stay open as long as you wantSupported but bounded by max request duration and instance lifecycle rules
Private networkingBuilt‑in private network across regions; WireGuard to connect your own infra; no public internet between servicesVia VPC connectors into Google VPC; more configuration and GCP‑specific networking concepts
Global proximity to usersAnycast routing + region placement; deploy “from Sydney to São Paulo” without separate edge stackRegion‑scoped; you can deploy in multiple regions but need to manage routing and traffic splitting
Stateful workloads (databases, etc.)Supported (e.g., Postgres, NVMe, object storage via Tigris); Machines + volumes for stateful servicesNot ideal; databases usually run on Cloud SQL / AlloyDB / GCE / GKE instead of Cloud Run
Scale‑to‑zeroAvailable; Machines can be stopped when idle and started on demand, billing per second for CPU and memory usageNative; idle instances scale to zero, billing per request and instance time
Operational controlDirect control over Machine lifecycle, placement, and restart policies; SSH into Machines for debuggingHigher level; instance lifecycle is abstracted, debugging often via logs / Cloud Debugger / other GCP tools
Ecosystem integrationFocused primitives (Machines, Sprites, Fly Proxy, Tigris storage); easy to integrate with external systems via WireGuard and public endpointsDeeply integrated with other Google Cloud services; best fit if you’re already “all‑in” on GCP
Isolation & sandboxingHardware‑virtualized Machines; Sprites for hardware‑isolated sandboxes to run untrusted/AI‑generated code safelyContainer isolation within Google’s infrastructure, but no explicit “per‑job microVM” concept exposed like Fly Machines

Ideal Use Cases

When Fly.io Is the Better Fit

  • Real‑time apps with heavy WebSocket usage
    Chats, games, dashboards, collaborative editors, or anything that keeps thousands of connections open for hours. Fly Machines don’t flinch at long‑lived sockets, and you can park them in regions nearest users.

  • Internal services on a global private network
    Microservices, internal APIs, and databases that should never traverse the public internet. Fly’s private networking and WireGuard integration make it straightforward to build a global “private LAN” for your app.

  • Stateful services plus compute, side by side
    If you want to run Postgres, caches, application services, and scheduled jobs all on the same platform without a separate “database product zoo,” Fly.io gives you the primitives to do that cleanly.

  • Running untrusted or AI‑generated code safely
    With Sprites, you can spin up hardware‑isolated sandboxes that start in under a second and have private networking by default. Perfect if you’re letting users run arbitrary code snippets or agents.

When Cloud Run Is the Better Fit

  • Purely stateless HTTP APIs and microservices
    Especially for teams already deep in GCP. You get easy wiring to Cloud SQL, Pub/Sub, Cloud Storage, and IAM with minimal friction.

  • Event‑driven workloads with tight GCP integration
    Things like “on GCS upload, run a container to transcode” or Pub/Sub‑driven microservices where each unit of work is relatively short and stateless.

  • Teams that want strict request‑driven autoscaling and don’t care about long‑lived connections
    If you never want to think about WebSockets, persistent TCP, or per‑instance lifecycle, Cloud Run’s model can be perfectly fine.


Limitations & Considerations

Fly.io Limitations / Things to Know

  • You’re closer to the metal.
    This is a feature for most platform engineers, but you do think about Machine counts, regions, and volumes explicitly. It’s not “ships code, magically scales,” it’s “ships code onto VMs that behave predictably.”

  • Learning curve if you’re used to only GCP abstractions.
    You’ll pick up flyctl, fly.toml, and the private networking model. It’s simpler than Kubernetes, but different from GCP’s world.

Cloud Run Limitations / Gotchas

  • Long‑lived and real‑time workloads are second‑class.
    WebSockets and multi‑minute connections run into timeout ceilings and unpredictable instance lifecycle events.

  • Private networking is powerful but complex.
    To get something equivalent to “all my services can talk privately,” you’re wiring VPC connectors, firewall rules, sometimes multiple projects, and reading a lot of docs.

  • Stateful or “VM‑like” expectations don’t fit.
    If you try to treat Cloud Run like a long‑running app server, you’ll spend time fighting autoscaling and lifecycle semantics.


Pricing & Cost Behavior (High Level)

Exact numbers change, but the economics are shaped by the models.

Fly.io

  • Billing is per‑Machine, per‑second for CPU, RAM, and storage.
  • Scale‑to‑zero means idle Machines can cost essentially nothing.
  • Because Machines are VMs, you can consolidate multiple responsibilities or keep fine‑grained, one‑per‑job Machines — you choose which is cheaper and easier to reason about.
  • No separate product for “WebSocket gateway,” “private networking,” or “edge” — these are built into the platform.

Google Cloud Run

  • Billing is per‑request plus per‑instance time while your container is handling requests.
  • Scale‑to‑zero is automatic; idle instances don’t cost you.
  • Real‑time apps with long‑lived connections can hold instances “busy” for a long time, which can be more expensive than short‑lived request workloads.
  • Advanced networking or stateful needs often drive you into additional paid services (VPC connectors, Cloud SQL, GCE, GKE).

Cost intuition:
If your app is chatty, long‑lived, and connection‑heavy, Fly.io’s model of “pay only for CPU/RAM seconds, not per request” tends to be saner. If you’re doing bursty, stateless HTTP and deeply integrated with GCP, Cloud Run can be very cost‑efficient.


Frequently Asked Questions

Can I run WebSockets and long‑running connections reliably on Fly.io?

Short Answer: Yes. WebSockets and long‑running TCP/HTTP connections are first‑class on Fly.io.

Details:
Fly Machines are long‑lived by design. Fly Proxy handles HTTP(S) and WebSocket upgrades and keeps those connections pinned to your Machines as long as your app wants them up. There’s no platform‑enforced “max request duration” cutting you off — if you want a WebSocket open for hours, that’s fine. You can also run these Machines in multiple regions to keep latency low for real‑time workloads.


How does Fly.io’s private networking compare to Cloud Run with a VPC connector?

Short Answer: Fly.io gives you a global, encrypted private network by default; Cloud Run requires VPC connectors and GCP networking setup.

Details:
On Fly.io, every app joins an organization‑scoped private network. Machines talk over this network with end‑to‑end encryption, even across regions, and you can plug in your own infra over WireGuard with a single fly wireguard create. There’s no extra “VPC product” to configure. On Cloud Run, you configure a VPC connector per service/region to access private resources in a Google VPC, then manage IAM and firewall rules. It’s powerful in an all‑GCP stack but more complex, and it doesn’t extend as cleanly to external infrastructure without VPNs or peering.


Summary

If you’re building long‑lived services, WebSocket‑heavy real‑time apps, or systems that rely on a clean private network between services, Fly.io is usually the sharper tool. Fly Machines act like fast‑booting VMs that can keep connections open indefinitely, Fly Proxy gives you global Anycast routing, and the private network plus WireGuard let your services talk off the public internet without getting a PhD in VPC design.

Google Cloud Run is a solid choice for stateless HTTP workloads and event‑driven jobs, especially if you’re already all‑in on GCP and don’t need persistent connections or stateful processes. Once you step into “this thing needs to stay up, keep a bunch of sockets open, and talk privately to other services,” Fly.io’s model matches the problem much more closely.


Next Step

Want to see how Fly Machines, private networking, and WebSockets feel in practice?
Get Started

Fly.io vs Google Cloud Run: which is better for long-lived services, websockets, and private networking? | Platform as a Service (PaaS) | Codeables | Codeables