Migrate from Fly.io

Move from Fly.io to RaidFrame — simpler networking, flat pricing, more built-in services.

Overview

Fly.io runs Docker containers on bare metal globally. RaidFrame does the same with a simpler mental model — no Fly Machines API, no fly.toml quirks, no surprise bills from idle machines you forgot about.

What Replaces What

Fly.ioRaidFrame
Fly MachinesContainer services
fly.tomlraidframe.yaml
fly deployrf deploy
fly postgresrf add postgres
Upstash Redis (Fly addon)rf add redis (managed)
Tigris (Fly addon)rf add storage
fly logsrf logs
fly scalerf services scale
fly ssh consolerf ssh
fly secretsrf secrets set
Fly Proxy / AnycastBuilt-in load balancer
Fly VolumesObject storage or persistent volumes
Fly ExtensionsBuilt-in services

Step 1: Export from Fly.io

fly.toml → raidframe.yaml

# fly.toml
app = "my-app"
primary_region = "iad"

[build]
  dockerfile = "Dockerfile"

[http_service]
  internal_port = 8080
  force_https = true
  auto_stop_machines = true
  auto_start_machines = true
  min_machines_running = 1

[[services]]
  internal_port = 8080
  protocol = "tcp"

  [[services.ports]]
    port = 443
    handlers = ["tls", "http"]

[env]
  NODE_ENV = "production"

Becomes:

# raidframe.yaml
project: my-app
region: us-east-1

services:
  web:
    type: web
    build:
      dockerfile: Dockerfile
    port: 8080
    scaling:
      min: 1
      max: 10
      scale_to_zero:
        idle_timeout: 15m

env:
  shared:
    NODE_ENV: production

Environment Variables

fly secrets list --json | jq -r '.[] | "\(.Name)=\(.Digest)"'
# Fly doesn't expose secret values — re-set them manually

rf secrets set DATABASE_URL=postgresql://... REDIS_URL=redis://... API_KEY=sk_live_...

Database

# Connect to Fly Postgres
fly postgres connect -a my-app-db

# From inside psql:
# \copy (SELECT * FROM users) TO '/tmp/users.csv' CSV HEADER;

# Or use pg_dump from outside
fly proxy 15432:5432 -a my-app-db &
pg_dump -h localhost -p 15432 -U postgres mydb > backup.sql

rf add postgres
rf db import main backup.sql

Volumes → Storage

Fly Volumes are local disk attached to machines. Move to object storage:

fly ssh console -a my-app
tar czf /tmp/data.tar.gz /data
exit

fly sftp get /tmp/data.tar.gz ./data.tar.gz -a my-app
tar xzf data.tar.gz

rf add storage
rf storage sync ./data/ s3://my-app-data/

Step 2: Deploy

rf deploy
rf domains add myapp.com

What You Gain

FeatureFly.ioRaidFrame
Pricing modelUsage-based (CPU/RAM per second)Flat per-service
Idle machine costsYou pay for forgotten machinesScale-to-zero or predictable flat
Managed PostgresFly Postgres (self-managed on Fly)Fully managed (backups, replicas, branching)
Managed RedisVia Upstash addon ($)Built-in (rf add redis)
Object storageVia Tigris addon ($)Built-in (rf add storage)
Message queuesNot built-inBuilt-in
SearchNot built-inBuilt-in
EmailNot built-inBuilt-in
Database branchingNot availableFork, test, merge
CI/CDNot built-in (use GitHub Actions)Built-in
Preview environmentsManualAutomatic per PR
Traffic mirroringNot availableMirror prod → staging
MCP integrationNot availableFull AI assistant support
Cost forecastingNot availablePredict and optimize

Fly.io-Specific Issues

Fly Machines vs Containers

Fly Machines are Firecracker microVMs. RaidFrame runs Docker containers. Your Dockerfile works identically — the runtime difference is transparent to your app.

Fly Multi-Region

On Fly, you fly scale count 2 --region iad,cdg. On RaidFrame:

rf regions add eu-west-1

Database read replicas follow automatically if configured.

Fly Wireguard

If you use Fly's private WireGuard network for development, RaidFrame has the same:

rf vpn connect

Fly Proxy / Replay Header

Fly uses a fly-replay header for multi-region request routing. On RaidFrame, latency-based routing is automatic. Remove any fly-replay logic from your app.