Claude Code for Fly Machines — Workflow Guide

Written by Michael Lip · Solo founder of Zovo · $400K+ on Upwork · 100% JSS Join 50+ builders · More at zovo.one

The Setup

You are deploying applications on Fly.io using Machines, the lightweight VM platform that starts in milliseconds and runs your Docker containers globally. Fly Machines provide fine-grained control over compute placement, auto-scaling, and geographic distribution. Claude Code can write Fly.io configurations, but it generates Heroku or AWS deployment patterns.

What Claude Code Gets Wrong By Default

  1. Creates Heroku Procfiles. Claude writes web: node server.js Heroku format. Fly.io uses fly.toml for configuration and Docker for builds — no Procfile needed.

  2. Uses AWS-style load balancer config. Claude configures ALB target groups. Fly.io handles load balancing automatically through its Anycast network — requests route to the nearest Machine based on the fly-replay header and geographic proximity.

  3. Ignores Fly’s multi-region capability. Claude deploys to a single region. Fly Machines can run in 30+ regions simultaneously, placing your app near users worldwide with fly machine clone --region nrt.

  4. Sets up external databases. Claude provisions RDS or PlanetScale. Fly provides built-in Postgres (fly postgres create), LiteFS for distributed SQLite, and Tigris for S3-compatible object storage.

The CLAUDE.md Configuration

# Fly.io Machines Project

## Platform
- Deploy: Fly.io (lightweight VMs, global distribution)
- Config: fly.toml at project root
- CLI: fly (flyctl)
- Build: Docker (Dockerfile required)

## Fly.io Rules
- Deploy: fly deploy (builds Docker, pushes, starts Machines)
- Config: fly.toml for app settings, scaling, services
- Regions: fly regions add nrt lhr iad (multi-region)
- Scale: fly scale count 3 (multiple Machines)
- Secrets: fly secrets set DATABASE_URL=... (encrypted)
- Postgres: fly postgres create (managed, Fly-internal)
- Volumes: fly volumes create data --region iad --size 10
- Health checks: configured in fly.toml [[services.checks]]

## Conventions
- Dockerfile at project root (multi-stage for production)
- fly.toml committed to version control
- Secrets via fly secrets set, never in fly.toml
- Health check endpoint: /health or /up
- Internal services: .internal hostname for service-to-service
- Volumes for persistent data (databases, uploads)
- Use fly proxy for local database access

Workflow Example

You want to deploy a Node.js API with a managed Postgres database. Prompt Claude Code:

“Deploy this Express app to Fly.io with a managed Postgres database. Configure auto-scaling from 1 to 5 machines, add health checks, and set up the DATABASE_URL secret.”

Claude Code should create/verify the Dockerfile, configure fly.toml with [[services]] for HTTP, [[services.checks]] for health, [processes] for the app, run fly postgres create for the database, attach it with fly postgres attach, and configure auto-scaling with fly autoscale set min=1 max=5.

Common Pitfalls

  1. Volume attachment across regions. Claude creates a volume in one region and tries to access it from Machines in other regions. Fly volumes are region-specific — a Machine can only mount volumes in the same region. Create volumes in each region where Machines run.

  2. Missing internal DNS for multi-service. Claude connects between Fly apps using public URLs. Fly apps communicate internally via appname.internal DNS over the private WireGuard network. Use internal addresses for service-to-service calls to avoid public network latency and egress.

  3. Fly Postgres is not managed RDS. Claude treats Fly Postgres like a fully managed service. Fly Postgres runs as a regular Fly app — you are responsible for backups, monitoring, and failover configuration. Set up fly postgres backup and monitoring.