---
name: fly
description: Use when deploying, configuring, scaling, or managing applications
  on Fly.io. Reach for this skill when working with Fly Launch (fly deploy,
  fly.toml), Machines, databases, networking, secrets, monitoring, or
  troubleshooting production issues on the platform.
metadata:
  mintlify-proj: fly
  version: "1.0"
---

# Fly.io Skill Reference

## Product summary

Fly.io is a platform for deploying and running applications on distributed Fly Machines (fast-launching VMs) across 17 global regions. Agents use **flyctl** (the CLI) and **fly.toml** (configuration file) to deploy apps with Fly Launch, manage Machines directly via the Machines API, attach persistent storage with Fly Volumes, and configure networking and secrets. The primary entry point is `fly launch` to scaffold a new app, followed by `fly deploy` to release changes. Key files: `fly.toml` (app config), `Dockerfile` (build definition), `.env` (local secrets). Critical commands: `fly launch`, `fly deploy`, `fly scale`, `fly secrets`, `fly logs`, `fly machine`. See [Fly.io docs](https://docs.fly.io) for comprehensive reference.

## When to use

- **Deploying apps:** User wants to launch a new application or redeploy changes. Use `fly launch` to scaffold, `fly deploy` to release.
- **Scaling:** User needs to add Machines, increase CPU/RAM, or autoscale based on metrics. Use `fly scale count`, `fly scale memory`, or `fly scale vm`.
- **Configuration:** User needs to set environment variables, secrets, health checks, or deployment strategy. Edit `fly.toml` or use `fly secrets set`.
- **Troubleshooting:** App is down, slow, or failing health checks. Check `fly logs`, `fly status`, `fly checks list`, or SSH with `fly ssh console`.
- **Networking:** User needs custom domains, private networking, or multi-region routing. Configure in `fly.toml` or use `fly ips`, `fly certs`.
- **Databases:** User needs Postgres, Redis, or persistent storage. Use `fly postgres create`, `fly redis create`, or `fly volumes create`.
- **CI/CD:** User wants automated deployments via GitHub Actions or custom workflows. Use `fly deploy` in Actions or the Machines API.

## Quick reference

### Essential flyctl commands

| Task | Command |
|------|---------|
| Create and deploy app | `fly launch` |
| Redeploy after changes | `fly deploy` |
| Check app status | `fly status` |
| View logs | `fly logs` |
| SSH into Machine | `fly ssh console` |
| Scale Machines | `fly scale count 3` |
| Scale CPU/RAM | `fly scale memory 512` |
| Set secrets | `fly secrets set KEY=value` |
| List secrets | `fly secrets list` |
| Create Postgres | `fly postgres create` |
| Create Redis | `fly redis create` |
| Create volume | `fly volumes create mydata --region ord` |
| Add custom domain | `fly certs add example.com` |
| Check health | `fly checks list` |
| View config | `fly config show` |

### fly.toml structure (essential sections)

```toml
app = "my-app"
primary_region = "ord"

[build]
  dockerfile = "Dockerfile"

[env]
  LOG_LEVEL = "info"
  RAILS_ENV = "production"

[http_service]
  internal_port = 8080
  force_https = true
  auto_stop_machines = "stop"
  auto_start_machines = true
  min_machines_running = 0

[[http_service.checks]]
  grace_period = "10s"
  interval = "30s"
  timeout = "5s"
  path = "/"

[deploy]
  strategy = "rolling"
  release_command = "bin/rails db:prepare"

[[mounts]]
  source = "mydata"
  destination = "/data"

[[processes]]
  name = "web"
  cmd = "bin/rails server"

[[processes]]
  name = "worker"
  cmd = "bundle exec sidekiq"
```

### Deployment strategies

| Strategy | Use case | Downtime | Constraints |
|----------|----------|----------|-------------|
| `rolling` (default) | Safe, gradual rollout | Minimal | Works with volumes |
| `canary` | Test one Machine first | Minimal | No volumes |
| `bluegreen` | Parallel boot, fast cutover | None | No volumes, needs health checks |
| `immediate` | Emergency rollback | Full | Use only when speed > safety |

### Machine states and transitions

- **created** → **started** → **stopped** → **destroyed**
- **started** → **suspended** (faster resume, clock skew risk)
- Machines auto-stop when idle if `auto_stop_machines = "stop"` or `"suspend"`
- Machines auto-start on request if `auto_start_machines = true`

## Decision guidance

### When to use Fly Launch vs Machines API

| Scenario | Use Fly Launch | Use Machines API |
|----------|---|---|
| Standard web app deployment | ✓ | |
| Multi-region scaling | ✓ | |
| One-off tasks or jobs | | ✓ |
| Fine-grained Machine control | | ✓ |
| Ephemeral workloads | | ✓ |
| Background workers | ✓ | |
| Rapid prototyping | ✓ | |

### When to use stop vs suspend

| Scenario | Use `stop` | Use `suspend` |
|----------|---|---|
| App uses JWTs or time-sensitive checks | ✓ | |
| Cold start latency critical | | ✓ |
| Clock skew tolerance low | ✓ | |
| Wake-up speed critical | | ✓ |
| Cron jobs or scheduled tasks | ✓ | |

### When to use volumes vs object storage

| Scenario | Use Volumes | Use Object Storage |
|----------|---|---|
| Database files (SQLite, LiteFS) | ✓ | |
| Persistent app state | ✓ | |
| Large media files | | ✓ |
| Backup/archive data | | ✓ |
| Multi-Machine shared data | | ✓ |
| Single-Machine local storage | ✓ | |

## Workflow

### Deploy a new app

1. **Scaffold:** Run `fly launch` in your project directory. Answer prompts for app name, region, and framework detection.
2. **Review config:** Check generated `fly.toml`. Verify `internal_port`, `primary_region`, and any custom settings.
3. **Set secrets:** Run `fly secrets set KEY=value` for sensitive data (database URLs, API keys).
4. **Deploy:** Run `fly deploy`. Watch logs with `fly logs` in another terminal.
5. **Verify:** Run `fly status` to check Machine health. Open app with `fly apps open`.

### Scale horizontally (add Machines)

1. **Check current state:** `fly status` shows running Machines.
2. **Scale out:** `fly scale count 3` creates 3 Machines total (or `fly scale count 3 --region ord,iad` for multi-region).
3. **Verify:** `fly status` shows new Machines. `fly checks list` confirms health checks pass.

### Scale vertically (increase CPU/RAM)

1. **Check current size:** `fly scale show` displays current Machine specs.
2. **Increase memory:** `fly scale memory 512` sets RAM to 512 MB.
3. **Increase CPU:** `fly scale vm performance-2x` upgrades to 2-core performance Machine.
4. **Verify:** `fly status` shows updated specs. Machines restart automatically.

### Deploy with zero downtime

1. **Configure health checks:** Add `[[http_service.checks]]` to `fly.toml` with appropriate `grace_period` (10-30s for slow startups).
2. **Choose strategy:** Set `strategy = "bluegreen"` for fastest zero-downtime (requires 2+ Machines and health checks).
3. **Deploy:** `fly deploy` boots new Machines, waits for health checks, then switches traffic.
4. **Monitor:** Watch `fly logs` and `fly checks list` during deploy.

### Troubleshoot a failing deployment

1. **Check logs:** `fly logs` shows app crashes, startup errors, or health check failures.
2. **Check health:** `fly checks list` shows which Machines are failing checks and why.
3. **SSH in:** `fly ssh console` opens a shell on a Machine to inspect state, environment, or logs.
4. **Validate config:** `fly config validate` catches syntax errors in `fly.toml`.
5. **Check status:** `fly status` shows Machine states. Stuck Machines may need `fly machine restart <id>` or `fly machine destroy --force <id>`.

### Set up a database

1. **Create:** `fly postgres create` (or `fly redis create` for Redis).
2. **Attach:** `fly postgres attach <db-app-name>` injects `DATABASE_URL` secret into your app.
3. **Connect:** `fly postgres connect` opens psql. Use `fly postgres proxy` to connect from your local machine.
4. **Verify:** `fly secrets list` shows `DATABASE_URL` is set. `fly deploy` to restart app with new secret.

## Common gotchas

- **App listens on wrong address:** App must listen on `0.0.0.0` (not `localhost` or `127.0.0.1`) on the port specified by `internal_port`. Fly Proxy connects from outside the Machine and can't reach localhost-only listeners.
- **Health check grace period too short:** Apps need time to start. Set `grace_period = "10s"` or higher for slow frameworks (Rails, Django, JVM apps). Without it, health checks fail during deploy and the deploy hangs.
- **Secrets not available at build time:** Secrets set with `fly secrets set` are only available at runtime. For build-time values, use `[build.args]` in `fly.toml`.
- **Volumes don't sync across Machines:** Fly Volumes are local to a single Machine. If you need shared storage, use object storage or a separate database app.
- **Canary and bluegreen can't use volumes:** These strategies temporarily run multiple Machines. Volumes can't be attached to multiple Machines, so use `rolling` strategy if you have volumes.
- **Suspend causes clock skew:** Machines resumed from suspend have incorrect system time briefly. This breaks JWT validation, cron jobs, and TLS checks. Use `auto_stop_machines = "stop"` if your app is time-sensitive.
- **Machines stop immediately after starting:** If your Dockerfile has no `CMD` or your app exits on startup, the Machine shuts down. Test locally with `docker run <image>` and check `fly logs` for exit codes.
- **502 Bad Gateway:** App crashed, isn't listening on the right port, or isn't ready yet. Check `fly logs` and increase health check grace period.
- **503 Service Unavailable:** No healthy Machines. Run `fly checks list` to see why health checks are failing. Check `fly status` to see if Machines are running.
- **Deployment timeout:** Large images or slow startups can exceed the 5-minute default timeout. Use `fly deploy --wait-timeout=10m` or set `wait_timeout = "10m"` in `[deploy]` section.
- **Release command fails:** Release commands run in a temporary Machine with no volumes. If you need to modify persistent data, use a process group command or app startup logic instead.
- **Can't connect to Postgres from local machine:** Managed Postgres runs on Fly's private network. Use `fly postgres proxy` to forward a local port, or `fly postgres connect` for psql.
- **Redis connection fails with IPv6 errors:** Fly's private network requires IPv6. Set `family: 6` in your Redis client config.
- **Custom domain TLS errors:** Ensure you have A and AAAA records (or a single CNAME), not a mix. If using Cloudflare, set SSL mode to "Full (strict)".
- **Outbound TCP connections fail:** Shared IPv4 addresses use the proxy, which only works for HTTP/TLS. For raw TCP (Redis, SMTP), allocate a dedicated IPv4 with `fly ips allocate-v4` or use `.internal` addresses for Fly-internal services.

## Verification checklist

Before submitting work:

- [ ] `fly config validate` passes without errors
- [ ] `fly status` shows all Machines in `started` state
- [ ] `fly checks list` shows all health checks passing
- [ ] `fly logs` shows no crash loops or errors in the last 30 seconds
- [ ] `fly secrets list` includes all required secrets (DATABASE_URL, API keys, etc.)
- [ ] `fly.toml` has correct `internal_port` matching app's listening port
- [ ] Health check `grace_period` is appropriate for app startup time (10-30s for slow frameworks)
- [ ] Deployment strategy is set correctly (`rolling` for volumes, `bluegreen` for zero-downtime without volumes)
- [ ] `release_command` (if used) runs successfully in `fly logs`
- [ ] App responds to requests: `fly apps open` or `curl https://<app>.fly.dev`
- [ ] For multi-region: `fly status` shows Machines in intended regions
- [ ] For databases: `fly secrets list` shows DATABASE_URL or REDIS_URL injected
- [ ] For volumes: `fly volumes list` shows volumes attached to correct Machines

## Resources

- **Comprehensive page listing:** [https://docs.fly.io/llms.txt](https://docs.fly.io/llms.txt) — full navigation of all Fly.io documentation pages
- **Fly Launch guide:** [https://docs.fly.io/launch/index](https://docs.fly.io/launch/index) — create, configure, deploy, and scale apps
- **App configuration reference:** [https://docs.fly.io/reference/configuration](https://docs.fly.io/reference/configuration) — complete fly.toml schema and options
- **Troubleshooting guide:** [https://docs.fly.io/getting-started/troubleshooting](https://docs.fly.io/getting-started/troubleshooting) — solutions for 502/503 errors, health checks, deployments, and common issues

---

> For additional documentation and navigation, see: https://docs.fly.io/llms.txt