fly-optimization
Fly.io Optimization
Opinionated best practices for consistent, production-ready Fly.io deployments.
Start here to determine the correct architecture, then load the appropriate reference doc for the full pattern.
Step 1: Determine Topology
Use [processes] in a single app when:
- Same codebase and Docker image
- Same deploy cadence (one deploy = both services redeploy, and that's fine)
- Shared secrets are acceptable across all processes
Use separate Fly apps when:
- Different codebases / repos
- Need independent deploy cadences
- Need secret isolation between services
- One service is public, another is internal-only and owned separately
Step 2: Determine Postgres
Fly MPG (Managed Postgres) — when ops overhead needs to be zero, client has no custom extension requirements, budget supports it (~$38+/mo base)
Fly pg (unmanaged) — when budget-conscious, need custom extensions (TimescaleDB etc), or comfortable owning db operations
External provider (Supabase, Neon, etc.) — when client already has a provider, needs features neither MPG nor fly pg offer, or Postgres needs to live outside Fly entirely
Step 3: Load the Reference Doc
Based on the above, load the relevant file from references/:
| Topology | Postgres | Reference doc |
|---|---|---|
| Process groups | Fly pg | references/process-groups-fly-pg.md |
| Process groups | MPG | references/process-groups-mpg.md |
| Process groups | External | references/process-groups-external.md |
| Separate apps | Fly pg | references/separate-apps-fly-pg.md |
| Separate apps | MPG | references/separate-apps-mpg.md |
| Separate apps | External | references/separate-apps-external.md |
Shared Conventions (apply to all patterns)
Naming
- Format:
{env}-{appname}— e.g.prod-myapp,staging-myapp - Separate Fly app per environment, same org
- Separate
fly.tomlper environment - Deploy:
fly deploy --config fly.prod.toml --app prod-myapp
Secrets
- Always
fly secrets set— no.envfiles, no committed credentials - Set independently per app and environment
- With process groups, secrets are shared across all groups — if isolation is needed, use separate apps instead
Autostop
- Default: off. Production apps keep machines running
- Exception: lightly-used background workers (e.g. image processing) use
auto_stop_machines = "suspend" - Prefer
"suspend"over"stop"— faster resume, same cost benefit at low traffic
Static Assets
Don't run a separate file server process for static assets. Fly can serve them directly from the proxy — it pulls them out of your container at deploy time and serves from the edge:
[[statics]]
guest_path = "/app/public"
url_prefix = "/public"
Faster than serving from your app, and one less process to manage.
Metrics
Fly includes a fully managed Prometheus + Grafana stack at fly-metrics.net. Built-in metrics (proxy, VM, OOM detection) are automatic. Custom metrics require a /metrics endpoint and a [metrics] block in fly.toml. See references/metrics.md.
Logging
Write to stdout. Fly captures it automatically. See references/logging.md for how the stack works and how to access logs.
All public-facing services expose GET /health returning 200 OK. Lightweight — no db queries unless gating on db connectivity is intentional.
[[http_service.checks]]
grace_period = "10s"
interval = "30s"
method = "GET"
path = "/health"
protocol = "http"
timeout = "5s"
Networking
- All apps in the same org share a private IPv6 network (6PN)
- Internal traffic uses
.internalDNS:http://prod-myapi.internal:3000 - Never route internal traffic through public URLs
- No public
[[services.ports]]on internal-only apps — absence of public ports = not internet-reachable, still 6PN-reachable
More from 0xrohan10/skills
write-a-prd
Use this skill when writing a PRD for a feature.
8finalize
Ship-readiness pass: review, fix, and validate working copy or PR changes. Use when asked to finalize, harden, do a final pass, or make code shippable.
3effect-logging
Logging, error handling, and observability patterns for Effect-TS API applications. Use this skill when the user is building an API or backend service with Effect-TS and needs guidance on structured logging, error modeling, tracing, log annotations, or observability setup. Also trigger when the user asks about Effect error handling patterns (Schema.TaggedErrorClass, defects vs failures, Cause), request-scoped logging context, Effect.fn tracing, log levels in Effect, or swapping logger implementations via layers. Trigger even if the user just mentions "logging" or "observability" alongside Effect/effect-ts — don't wait for them to name specific APIs.
3