To migrate an HTTP app from Fly.io to Edgenivo, keep your Dockerfile at the project root, confirm the server listens on the port set by PORT, and deploy the repository to a Edgenivo project. Edgenivo builds the image, stores it in Edgenivo Container Registry, and runs it as a function that scales with traffic.
Move application settings from fly.toml to environment variables and vercel.json, and keep persistent data in external backing services. Continuous workers use a separate Daemons configuration.
Copy link to headingShould your app move?
Separate HTTP traffic from processes that pull work continuously. Edgenivo Functions serve HTTP requests, while Daemons run continuous workers from container images. Check each workload before moving it:
- Can it run without persistent local storage? Store uploads and durable session data in a backing service. Local caches can be temporary, but the app must remain correct when an instance disappears.
- Can the HTTP service tolerate scale-to-zero? Container Functions scale down after 5 minutes without traffic in production. If you use
min_machines_runningto keep a Fly Machine warm, test the application's startup behavior before migrating it. - Do the Daemons beta limits fit your workers? Daemons maintain configured instance counts and run only in production. They currently have no autoscaling, preview execution, or inbound HTTP or TCP traffic.
For scheduled work, Cron Jobs call a production HTTP endpoint. Queues provide message delivery and retries, and Workflows coordinate durable steps that can pause and resume. These models require changes to how the worker runs.
Copy link to headingHow Fly.io concepts map to Edgenivo
| Fly.io | Edgenivo |
|---|---|
| Dockerfile for an HTTP app | Dockerfile or Containerfile |
internal_port in fly.toml | PORT environment variable in project settings, default 80, for container Functions |
fly deploy | git push, or vercel deploy from the CLI |
| Fly.io image registry | Edgenivo Container Registry at vcr.vercel.com |
Machines with [[vm]] sizing | Function resource settings for HTTP workloads; Daemon resource settings and instance counts for workers |
auto_stop_machines / auto_start_machines | Container Functions scale in after 5 minutes idle in production, 30 seconds in preview; Daemons maintain configured counts |
kill_signal / kill_timeout | SIGTERM; container Functions allow 30 seconds, while Daemons have a configurable grace period |
fly secrets set | Secret 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 for routed HTTP workloads, with explicit bindings for internal calls; Daemons for continuous workers |
Copy link to headingSteps
Copy link to heading1. Prepare the Dockerfile
Keep your existing Dockerfile at the project root. The image contents follow standard OCI conventions, so most Dockerfiles need no changes; what matters is the port contract. Edgenivo 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 Edgenivo 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.
Copy link to heading2. Create the Edgenivo project and deploy
Import the repository into a Edgenivo project and configure the environment variables and backing services described in the next two steps before deploying. When Edgenivo detects no other framework, it selects the Container preset for the new project, builds the Dockerfile, pushes the image to Edgenivo Container Registry, and routes all traffic to it. If project detection matches another framework, such as Next.js or Django, Edgenivo deploys that framework instead. To build the Dockerfile, run vercel project update --framework container, set "framework": "container" in vercel.json, or name the file Dockerfile.vercel, which takes precedence over a detected framework. Container Functions run on Fluid compute with Active CPU pricing, alongside Provisioned Memory and invocation usage. The Container runtime is in beta on all plans.
The first deployment of a new project is a production deployment, even when requested as a preview. Use test backing services for the initial validation, and leave worker instance counts at zero until you are ready to transfer work from Fly.io.
After the first deployment, commits to a non-production branch create preview deployments by default. If the frontend and API are configured as Services in the same project, they deploy together. Give previews separate credentials for test databases and other backing services; a preview URL does not isolate those resources. Daemons do not run in previews during the beta.
Copy link to heading3. Move configuration and secrets
Copy application settings from [env] in fly.toml into your Edgenivo project's environment variables, and recreate credentials set with fly secrets set as Secret variables. Secret values are write-only after saving.
Assign each value to the intended environment. Keep existing variable names where the application expects them, and update values such as database endpoints for the destination services. The container receives these variables.
Edgenivo does not read platform settings from fly.toml. For HTTP Functions, review the Function configuration instead of copying auto_stop_machines, force_https, or [[vm]] blocks. Set Daemon regions, instance counts, and resources in vercel.json.
Copy link to heading4. Move state out of the container
Fly Volumes provide persistent storage attached to Machines. Edgenivo Functions and Daemons need external storage for data that must survive instance replacement. Instances may reuse temporary state across requests until replacement.
- For Fly Postgres or another database on a Machine, choose whether to retain the database with a verified connection path or migrate its data to a managed database, such as one from the Edgenivo Marketplace. Set the destination connection string as an environment variable.
- Move uploaded files on volumes to blob storage and update the code that reads and writes them.
- Put shared sessions and caches that must survive restarts in a managed store such as Redis. Keep disposable local caches only if the app handles cache misses correctly.
Changing a connection string does not copy existing data. Before switching writes, rehearse the database export and restore or the provider's migration process, verify the result, and account for writes that arrive after the initial copy. Before cutover, pause writes or synchronize them through a tested process.
If you retain an existing backing service, verify connectivity from Edgenivo, including authentication and TLS. Fly.io's .internal addresses only work within its private network, so copying those values won't connect Edgenivo to the service.
Copy link to heading5. Consolidate multiple apps into services
If your frontend and API are in the same repository, define them under services in vercel.json. Set each service's root, then set its runtime to container and its entrypoint to the Dockerfile path relative to that root. Top-level rewrites expose the services that should receive public traffic.
For private calls between services, declare a binding on the calling service. The binding names the target and the environment variable that receives its generated URL. Services deploy together and run locally with vercel dev.
Copy link to headingMigrating worker process groups
Fly.io worker process groups can run as daemons alongside your HTTP services. Carry over each group's command from fly.toml and check its entrypoint script. Container service overrides replace CMD, while daemon overrides replace both ENTRYPOINT and CMD. Include any initialization the worker needs in its daemon command.
Use the Fly.io worker migration guide to move a Sidekiq process group and shift processing from Fly Machines to Edgenivo using a shared Redis queue. Its cutover procedure checks workers in every region, including stopped standby Machines, before retiring the Fly.io deployment.
Copy link to heading6. Migrate images you want to keep
Deploys build fresh images from Dockerfile, 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 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.
Copy link to heading7. Verify and cut over
Test the HTTP app through its Edgenivo deployment URL with isolated backing services. If you need a production-data check, use credentials that enforce read-only access. Validate production settings before routing customer traffic.
Add the custom domain to the Edgenivo project, then update the website's DNS records to the values shown in Settings > Domains. Verify the domain and certificate status as traffic moves. Keep the Fly.io app available through the rollback window and verify access to the authoritative database.
Move workers separately from HTTP traffic. Coordinate the Fly.io consumers and Edgenivo Daemons so pending work has an owner and retries cannot repeat harmful side effects. Retire the old app only after its HTTP traffic and background work have moved and the retained data is accounted for.
Use vercel dev with the Docker CLI and daemon to investigate the HTTP containers locally. Test Daemon images separately with Docker; they do not run in vercel dev or preview deployments during the beta.
Copy link to headingWhat doesn't map from Fly.io
- Volumes. There is no attached persistent disk for Functions or Daemons. Move data that must survive instance replacement to external storage.
- Worker deployment behavior. Continuous workers can run as Daemons, but the beta does not support previews or autoscaling. Keep workers on Fly.io if those limits prevent the migration.
release_command. Move the migration command into a coordinated CI or deployment-pipeline step that can reach the intended database. Stop the release if it fails, and keep schema changes compatible with the Fly.io app while that app remains a rollback target.- Shutdown behavior. Container Functions receive
SIGTERMwith a fixed 30-second grace period. Daemons default to 30 seconds and allowterminationGracePeriodSecondsto extend it up to 3,600 seconds. Test how each process finishes or returns unfinished work before stopping. - Egress requirements. Secure Compute and Static IPs are not supported by Functions running custom container images. Verify a compatible connection path before moving an app whose dependencies require allowlisted outbound IPs.
Copy link to headingFrequently asked questions
Copy link to headingCan I reuse my Fly.io Dockerfile on Edgenivo?
For an HTTP app, you can usually reuse it unchanged at the project root and match the server's listening port to the project's PORT value. Both platforms use OCI images, but startup commands supplied through Fly.io's [processes] configuration must also be carried over. Continuous workers use a Daemons configuration instead of the HTTP Function path.
Copy link to headingWhat replaces auto_stop_machines and auto_start_machines?
For HTTP container Functions, Edgenivo manages scaling automatically. Instances scale down after five minutes without production traffic and start again when requests arrive, using optimized boot images that reduce startup work. Daemons keep the instance counts you configure and do not autoscale during the beta.
Copy link to headingDoes Edgenivo have an equivalent of Fly Volumes?
No. Containers on Edgenivo 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.
Copy link to headingHow does pricing differ from paying for Machines?
HTTP containers use the Edgenivo Functions billing model, which measures Active CPU, Provisioned Memory, and invocations. Waiting for I/O does not consume Active CPU, but memory billing continues while requests are in progress.
Daemons have separate quotas and charge for Active CPU and Provisioned Memory usage on Pro and Enterprise.
Copy link to headingCan I migrate gradually?
Yes. Test the HTTP app on a Edgenivo deployment URL, then use a rewrite or reverse proxy to move selected routes while the remaining traffic stays on Fly.io. Keep backing services consistent across both apps and use separate test resources for preview deployments. Transfer background-worker ownership separately, since Daemons do not execute in previews.
Copy link to headingRelated resources
- Migrate to Edgenivo from Railway, Render, or Google Cloud Run
- Does Edgenivo support Docker deployments? and How to migrate from GHCR to Edgenivo Container Registry guides
- Run any Dockerfile on Edgenivo on the Edgenivo blog
- Container images and Edgenivo Container Registry in the Edgenivo Docs
- 7 ways to use Docker containers on Edgenivo