# Fly.io vs Heroku

Canonical: https://inetgeek.com/compare/fly-io-vs-heroku/

Every value below is read from Fly.io's and Heroku's own documentation. See https://inetgeek.com/methodology/ for how.

## At a glance

| Criterion | Fly.io | Heroku |
| --- | --- | --- |
| Pricing model | Usage-based, no compute plan tiers | Usage-based on wall-clock time, prorated to the second |
| When you exceed a cap | No plan cap to exceed — Fly bills per second for provisioned resources. The only documented enforcement is unspecified automated scaling limits, which surface as an error message (platform-wide, all plans) | Service sleeps: on the Eco plan ($5/month for a 1000 dyno-hour pool, the cheapest paid tier) exhausting the pool forces every Eco dyno on the account to sleep for the rest of the month, and extra hours cannot be bought |
| Memory (entry plan) | 256MB on shared-cpu-1x, the smallest Machine size ($2.02/month at the Amsterdam-region rate shown in the pricing table) | 0.5 GB RAM on the Eco dyno ($5 flat/month, the cheapest paid dyno) and 0.5 GB on the Basic dyno ($7/month) |
| File or inode limit | 8 GB rootfs (deployed image) limit per Machine, platform-wide on all plans; exceeding it fails the image push at deploy time | 1000 MB maximum compressed slug size, platform-wide on all plans; raisable via support ticket |
| Streaming response limit | No duration or size ceiling documented. Streaming works, but Fly Proxy buffers responses before compressing them, so progressive server-side rendering needs Content-Encoding: none set on those responses. | Platform-wide (router): 30 seconds to send the first byte, then a rolling 55-second idle window — if no data is sent for 55 seconds the connection is terminated |
| Managed connection pooling | Supported | Limited |
| Docker deployment | Supported | Supported |
| Scheduled jobs | Limited | Supported |
| Persistent storage | Supported | Not supported |
| Managed databases | Supported | Supported |
| Scales to zero | Supported | Limited |
| Autoscaling | Limited | Limited |
| Regions | 18 regions | 2 regions on the Common Runtime, which is what a standard dyno runs in: eu (Europe) and us (United States). A further 10 — Dublin, Frankfurt, London, Montreal, Mumbai, Oregon, Singapore, Sydney, Tokyo and Virginia — exist only in Private Spaces, an Enterprise product. |

## Where they differ

### Pricing model

- Fly.io: Usage-based, no compute plan tiers ([source](https://fly.io/docs/about/pricing/))
- Heroku: Usage-based on wall-clock time, prorated to the second ([source](https://devcenter.heroku.com/articles/usage-and-billing))

### When you exceed a cap

- Fly.io: No plan cap to exceed — Fly bills per second for provisioned resources. The only documented enforcement is unspecified automated scaling limits, which surface as an error message (platform-wide, all plans) ([source](https://fly.io/docs/about/pricing/))
- Heroku: Service sleeps: on the Eco plan ($5/month for a 1000 dyno-hour pool, the cheapest paid tier) exhausting the pool forces every Eco dyno on the account to sleep for the rest of the month, and extra hours cannot be bought ([source](https://devcenter.heroku.com/articles/eco-dyno-hours))

### Memory (entry plan)

- Fly.io: 256MB on shared-cpu-1x, the smallest Machine size ($2.02/month at the Amsterdam-region rate shown in the pricing table) ([source](https://fly.io/docs/about/pricing/))
- Heroku: 0.5 GB RAM on the Eco dyno ($5 flat/month, the cheapest paid dyno) and 0.5 GB on the Basic dyno ($7/month) ([source](https://devcenter.heroku.com/articles/dyno-types))

### File or inode limit

- Fly.io: 8 GB rootfs (deployed image) limit per Machine, platform-wide on all plans; exceeding it fails the image push at deploy time ([source](https://fly.io/docs/getting-started/troubleshooting/))
- Heroku: 1000 MB maximum compressed slug size, platform-wide on all plans; raisable via support ticket ([source](https://devcenter.heroku.com/articles/limits))

### Streaming response limit

- Fly.io: No duration or size ceiling documented. Streaming works, but Fly Proxy buffers responses before compressing them, so progressive server-side rendering needs Content-Encoding: none set on those responses. ([source](https://fly.io/docs/reference/content-encoding/))
- Heroku: Platform-wide (router): 30 seconds to send the first byte, then a rolling 55-second idle window — if no data is sent for 55 seconds the connection is terminated ([source](https://devcenter.heroku.com/articles/request-timeout))

### Managed connection pooling

- Fly.io: Supported ([source](https://fly.io/docs/mpg/cluster-configuration/))
- Heroku: Limited ([source](https://devcenter.heroku.com/articles/postgres-connection-pooling))

### Scheduled jobs

- Fly.io: Limited ([source](https://fly.io/docs/machines/flyctl/fly-machine-run/))
- Heroku: Supported ([source](https://devcenter.heroku.com/articles/scheduler))

### Persistent storage

- Fly.io: Supported ([source](https://fly.io/docs/volumes/overview/))
- Heroku: Not supported ([source](https://devcenter.heroku.com/articles/dynos))

### Scales to zero

- Fly.io: Supported ([source](https://fly.io/docs/launch/autostop-autostart/))
- Heroku: Limited ([source](https://devcenter.heroku.com/articles/eco-dyno-hours))

### Regions

- Fly.io: 18 regions ([source](https://fly.io/docs/reference/regions/))
- Heroku: 2 regions on the Common Runtime, which is what a standard dyno runs in: eu (Europe) and us (United States). A further 10 — Dublin, Frankfurt, London, Montreal, Mumbai, Oregon, Singapore, Sydney, Tokyo and Virginia — exist only in Private Spaces, an Enterprise product. ([source](https://devcenter.heroku.com/articles/regions))

## Which should you choose?

Pick Fly.io if Workloads that ship as Docker images and need placement in particular regions. Billing is purely usage-based with no plan tiers, which suits spiky or region-pinned traffic better than a flat monthly fee.

Pick Heroku if Teams that want to deploy by pushing to Git and let the platform handle the runtime, with Postgres, a scheduler and Docker deploys available on the same platform.

Consider something else: Fly.io — You want a predictable flat bill rather than charges that track the resources provisioned for each app.

Consider something else: Heroku — The dyno filesystem is ephemeral, and a web process must respond within 30 seconds of receiving a request.

## Documented by only one

- Entry paid plan: Heroku: $5 per month (Eco dynos plan, 1000 dyno hours shared across the account)
- Egress over allowance: Fly.io: $0.02 per GB (North America / Europe); $0.04 per GB (Asia Pacific / Oceania / South America); $0.12 per GB (Africa / India)
- Sites or apps included: Heroku: 100 apps per account, platform-wide on all plans (Heroku Team 100, Enterprise Team 200)
- Concurrent builds: Heroku: 10 concurrent builds for verified users without an established payment history; 300 for verified users with one (platform-wide, all plans)
- Max request duration: Heroku: 30 seconds (initial window for the web process to return response data)
- CPU time limit: Fly.io: Platform-wide, per Machine size: shared vCPUs get a 5ms CPU quota per 80ms period (6.25%); performance vCPUs get the full 80ms. Quotas are shared across a Machine's vCPUs, and tasks are throttled for the rest of the period once the quota is reached.
- Git deployment: Heroku: Supported
- Containers: Heroku: Supported
- Persistent processes: Heroku: Supported
- Edge network: Fly.io: Limited

## Questions this comparison answers

**When you exceed a cap: Fly.io or Heroku?**

Fly.io: No plan cap to exceed — Fly bills per second for provisioned resources. The only documented enforcement is unspecified automated scaling limits, which surface as an error message (platform-wide, all plans)
Heroku: Service sleeps: on the Eco plan ($5/month for a 1000 dyno-hour pool, the cheapest paid tier) exhausting the pool forces every Eco dyno on the account to sleep for the rest of the month, and extra hours cannot be bought

**Should I choose Fly.io or Heroku?**

Pick Fly.io if Workloads that ship as Docker images and need placement in particular regions. Billing is purely usage-based with no plan tiers, which suits spiky or region-pinned traffic better than a flat monthly fee.
Pick Heroku if Teams that want to deploy by pushing to Git and let the platform handle the runtime, with Postgres, a scheduler and Docker deploys available on the same platform.
