---
title: How to migrate from Fly.io to Vercel
description: Move a containerized app from Fly.io to Vercel. Map fly.toml to Dockerfile.vercel and vercel.json, replace Machines with Fluid compute, move volumes to external storage, and cut over without downtime.
url: /kb/guide/migrate-fly-io-to-vercel
canonical_url: "https://vercel.com/kb/guide/migrate-fly-io-to-vercel"
published: 2026-08-11
last_updated: 2026-08-11
authors: Ben Sabic
related:
  - /kb/guide/does-vercel-support-docker-deployments
  - /docs/container-registry
  - /docs/functions/container-images
  - /blog/dockerfile-on-vercel
  - /kb/guide/migrate-ghcr-to-vcr
  - /kb/guide/migrate-railway-to-vercel
install_vercel_plugin: npx plugins add vercel/vercel-plugin
---

To migrate from [Fly.io](http://Fly.io) to Vercel, rename your Dockerfile to `Dockerfile.vercel`, make sure it serves HTTP on the port in the `PORT` environment variable, and push to a Vercel project. Vercel [builds the image, stores it in Vercel Container Registry, and runs it as a function](https://vercel.com/kb/guide/does-vercel-support-docker-deployments) that scales with traffic. Configuration moves from `fly.toml` to environment variables and `vercel.json`, and stateful pieces such as Fly Volumes move to external backing services.

This guide maps each Fly.io concept to its Vercel equivalent, walks through the migration, and is direct about what doesn't carry over.

## Should your app move?

Vercel runs containers as stateless HTTP services. The fit test comes down to three questions:

- **Does the app serve HTTP and keep no state between requests?** Sessions, uploads, and caches must live in a backing service, not on local disk or in process memory.
  
- **Does it tolerate scale-to-zero?** Instances scale down after 5 minutes of inactivity in production. If you run Machines with `min_machines_running` above zero because the app can't cold start, resolve that first.
  
- **Is it request-driven?** Background workers, queue consumers, and cron processes that run outside the request cycle have no container equivalent on Vercel and should either be left behind or restructured.
  

If the app is a web service or API that happens to run in a container, it moves cleanly. If it depends on attached volumes or always-on processes, continue reading for what doesn't map before starting.

## How Fly.io concepts map to Vercel

| Fly.io                                       | Vercel                                                                                              |
| -------------------------------------------- | --------------------------------------------------------------------------------------------------- |
| `Dockerfile`                                 | `Dockerfile.vercel` (or `Containerfile.vercel`)                                                     |
| `internal_port` in `fly.toml`                | `PORT` environment variable in project settings, default 80                                         |
| `fly deploy`                                 | `git push`, or `vercel deploy` from the CLI                                                         |
| Fly.io image registry                        | [Vercel Container Registry](https://vercel.com/docs/container-registry) at `vcr.vercel.com`         |
| Machines with `[[vm]]` sizing                | Fluid compute, no instances to size                                                                 | | `auto_stop_machines` / `auto_start_machines` | Automatic: scale-in after 5 minutes idle in production, 30 seconds in preview                       | | `kill_signal` / `kill_timeout`               | `SIGTERM` with a 30-second grace period                                                             | | `fly secrets set`                            | Sensitive environment variables in project settings                                                 | | `[env]` in `fly.toml`                        | Environment variables in project settings                                                           | | Fly Volumes                                  | External storage: databases, caches, or blob storage                                                | | Multiple apps or process groups              | [Services](https://vercel.com/docs/functions/container-images) in one project, routed with rewrites |

## Steps

### 1\. Prepare the Dockerfile

Copy your existing `Dockerfile` to `Dockerfile.vercel` at the project root. The image contents follow standard OCI conventions, so most Dockerfiles need no changes; what matters is the port contract. Vercel routes traffic to the port in the `PORT` environment variable, which defaults to 80. On Fly.io, the port lives in `fly.toml` as `internal_port`, and the app itself often hardcodes it.

If your server already reads `PORT` from the environment, as most Fly.io apps do, nothing changes. If it hardcodes a port, you have two options: update the code to read `PORT`, or set `PORT` in your Vercel project settings to the port the server listens on. Don't rely on an `ENV PORT` line in the Dockerfile to change where traffic routes; the routed port comes from project settings, not the image.

### 2\. Create the Vercel project and deploy

Import the repository into a new Vercel project. Vercel detects `Dockerfile.vercel`, builds the image on every commit, pushes it to Vercel Container Registry, and serves it on Fluid compute with [Active CPU pricing](https://vercel.com/blog/dockerfile-on-vercel), so you pay for the CPU your code uses rather than for provisioned Machines.

Every commit also gets a preview deployment with its own URL, replacing the staging [Fly.io](http://Fly.io) app pattern: instead of maintaining a second app for testing, every branch automatically gets an isolated environment.

### 3\. Move configuration and secrets

Copy the `[env]` section of `fly.toml` into your Vercel project's environment variables, and recreate anything set with `fly secrets set` as sensitive environment variables. Vercel injects both into the container at runtime the same way Fly.io does, so application code doesn't change. `fly.toml` settings that configured the platform rather than the app, such as `auto_stop_machines`, `force_https`, and `[[vm]]` blocks, have no destination: scale-to-zero and HTTPS are automatic, and there are no instances to size. ### 4\. Move state out of the container This is the step that decides the migration. On Fly.io, a Machine can mount a volume and keep state locally; on Vercel, each container instance takes a request, responds, and keeps nothing: - **Fly Postgres or a database on a Machine** moves to a managed database, such as one from the Vercel Marketplace, and the connection string is set as an environment variable.    - **Files on volumes** move to blob storage.    - **In-process caches and sessions** are moved to a managed cache, such as Redis.    If the app already ran with external state on Fly.io, as many do, this step is only connection strings. ### 5\. Consolidate multiple apps into services Where you ran separate Fly.io apps for a frontend and an API, or process groups in one app, define each as a service in `vercel.json`. Set each container-backed service's `runtime` to `container` and point its `entrypoint` at that service's Dockerfile, then route between services with rewrites. Vercel generates environment variables for each service, so they call each other without hardcoded URLs, and the whole project deploys to one domain and runs locally with a single command. ### 6\. Migrate images you want to keep Deploys build fresh images from `Dockerfile.vercel`, so most teams don't need to move old images at all. If you keep release images for rollback or compliance, copy them into VCR with standard Docker tooling; the commands in the [GHCR migration guide](https://vercel.com/kb/guide/migrate-ghcr-to-vcr) work against any OCI registry, including Fly.io's. Run `fly auth docker` first to authenticate Docker with Fly.io's registry, then `docker buildx imagetools create` copies multi-platform images without pulling layers locally.

### 7\. Verify and cut over

Run the app at its Vercel preview URL against production backing services on read-only paths first, then shift traffic by updating DNS to point to the Vercel deployment. Keep the Fly.io app running until Vercel serves production traffic cleanly, then scale Machines down and remove the app. Because the container also runs locally with `vercel dev`, using the Docker daemon on your machine, you can reproduce any behavior difference before cutover rather than after.

## What doesn't map from Fly.io

- **Volumes.** There is no attached persistent disk. If the app writes anything to local paths it expects to survive restarts, that data must move to external storage before migrating.
  
- **Always-on processes.** Background workers and queue consumers aren't request-driven, so they don't fit the container-as-function model. Keep them where they are, or restructure them to focus on request-triggered work.
  
- `**release_command**`**.** There's no deploy-time hook for migrations. Run them from CI before the deploy, or from a separate step in your pipeline.
  
- **Long shutdown windows.** Fly.io lets you set `kill_timeout`; on Vercel the grace period after `SIGTERM` is fixed at 30 seconds. If cleanup takes longer, shorten it.
  
- **Two networking features.** Secure Compute and Static IPs aren't supported with custom container images yet. If you allowlist Fly.io egress IPs with an external service today, plan around that.
  

## Frequently asked questions

### Can I reuse my Fly.io Dockerfile on Vercel?

Yes, usually unchanged. Copy it to `Dockerfile.vercel` and confirm the server reads its port from the `PORT` environment variable. The image itself follows standard OCI conventions on both platforms.

### What replaces auto\_stop\_machines and auto\_start\_machines?

Nothing to configure. Vercel scales container instances down automatically after five minutes without traffic in production and back up when traffic returns. Images are stored as precompiled snapshots in Vercel Container Registry, which keeps cold starts fast.

### Does Vercel have an equivalent of Fly Volumes?

No. Containers on Vercel are stateless, so persistent data lives in external services: a managed database, cache, or blob storage. Anything the app writes to local disk exists only for the life of that instance.

### How does pricing differ from paying for Machines?

On Vercel you don't provision or size instances. Containers run as Vercel Functions with Active CPU pricing, so cost follows the CPU time your code uses, and idle time isn't billed as a running Machine.

### Can I migrate gradually?

Yes. Vercel preview deployments run the containerized app on real URLs before any DNS change, so you can test against production backing services, move read-only traffic first, and keep the [Fly.io](http://Fly.io) app running until you've verified the cutover.

## Related resources

- [Does Vercel support Docker deployments?](https://vercel.com/kb/guide/does-vercel-support-docker-deployments) and [How to migrate from GHCR to Vercel Container Registry](https://vercel.com/kb/guide/migrate-ghcr-to-vcr) guides
  
- [How to migrate from Railway to Vercel?](https://vercel.com/kb/guide/migrate-railway-to-vercel) guide
  
- [Run any Dockerfile on Vercel](https://vercel.com/blog/dockerfile-on-vercel) on the Vercel blog
  
- [Container images](https://vercel.com/docs/functions/container-images) and [Vercel Container Registry](https://vercel.com/docs/container-registry) in the Vercel Docs
  
- [7 ways to use Docker containers on Vercel](https://vercel.com/i/7-ways-to-use-docker-containers-on-vercel)