Machines
A Fly.Machine is a Firecracker VM
running a container image. Use it when you already have an image.
Launch a Machine
Section titled “Launch a Machine”The parent is an App. Pin a region, an image, and a guest:
const web = yield* Fly.Machine("Web", { app: Site, region: "iad", image: "nginx:alpine", guest: { cpuKind: "shared", cpus: 1, memoryMb: 256 }, services: [ { protocol: "tcp", internalPort: 80, ports: [ { port: 80, handlers: ["http"], forceHttps: true }, { port: 443, handlers: ["tls", "http"] }, ], }, ],});region replaces on change. image updates in place by default; the
opt-in blue/green strategy prepares replacement Machines instead. Guest
defaults to shared-cpu 1× / 256 MB. Port 443 with tls is what
makes https://{app}.fly.dev answer. Omit services (or pass
[]) for a worker that should not be reachable from the internet.
{app}.fly.dev over IPv4 still needs an
IpAssignment on the parent App.
Run named containers
Section titled “Run named containers”Use containers for a group that shares one Machine. Each named container has its own image and can set cmd, entrypoint, env, startup dependsOn, and Pilot healthChecks. Use cmd and entrypoint to override startup; container exec overrides are not supported. Existing single-image init.exec is unchanged. Check intervals and timeouts are numeric seconds. A dependency condition can be started, healthy, or exited_successfully.
const preview = yield* Fly.Machine("Preview", { app: Site, region: "iad", guest: { cpus: 1, memoryMb: 1024 }, containers: [ { name: "api", image: apiImage, healthChecks: [{ http: { port: 3000, path: "/health" } }] }, { name: "worker", image: workerImage, dependsOn: [{ name: "api", condition: "healthy" }] }, ],});count duplicates the entire group. A rolling change to one container can restart the whole group; attached volumes stay with their Machine. Machine env and bindings remain shared, while container env is passed to Fly as a per-container override. Configure Machine or service readiness checks for every critical component before treating a deploy as ready: Pilot container checks and dependencies control startup, not Alchemy’s rollout readiness. Blue/green also supports named containers when every image is an immutable
repository@sha256: digest and no volumes are attached. It replaces the
whole group and can overlap old and new workers during promotion.
If a rolling update is interrupted, Fly may have accepted the update even though the CLI reported a failure. Wait for the in-progress Machine update to settle, then rerun the same desired deployment. Reconciliation reuses the owned Machine and its attached volumes.
Scale up
Section titled “Scale up”A Machine resource runs one VM by default. Set count to manage
several replicas together, or declare separate resources for Machines
with different configuration. Fly’s proxy load-balances published
services across them.
const web1 = yield* Fly.Machine("Web1", { app: Site, region: "iad", image: "nginx:alpine", services: [ { protocol: "tcp", internalPort: 80, ports: [ { port: 80, handlers: ["http"], forceHttps: true }, { port: 443, handlers: ["tls", "http"] }, ], }, ],});
const web2 = yield* Fly.Machine("Web2", { app: Site, region: "iad", image: "nginx:alpine", services: [ { protocol: "tcp", internalPort: 80, ports: [ { port: 80, handlers: ["http"], forceHttps: true }, { port: 443, handlers: ["tls", "http"] }, ], }, ],});Both Fly.Machine and Service support
count. With the default rolling strategy, replicas within one resource
update sequentially; separate resources do not share that ordering.
Blue/green prepares the desired replacement topology before old retirement.
count is provisioned capacity, not always-running capacity. With
autostop: "stop" or "suspend", replicas may be idle. autostart allows
requests to wake them, and minMachinesRunning controls Fly’s running floor.
Blue/green checks a running representative plus the required floor without
permanently waking all idle replicas. A replacement does not inherit suspended
RAM. See idle-capacity semantics.
Scale down
Section titled “Scale down”Remove a Machine from the stack. The next deploy deletes it.
const web1 = yield* Fly.Machine("Web1", { app: Site, region: "iad", image: "nginx:alpine",});
const web2 = yield* Fly.Machine("Web2", { app: Site, region: "iad", image: "nginx:alpine",});Env, restart, metadata
Section titled “Env, restart, metadata”const worker = yield* Fly.Machine("Worker", { app: Site, region: "iad", image: "my-image:tag", env: { LOG_LEVEL: "info" }, restart: { policy: "always" },});Alchemy stamps alchemy.stack / alchemy.stage / alchemy.id /
alchemy.type onto config.metadata so list() can find owned
Machines. Fly injects App secrets as env vars
on the Machine. minSecretsVersion requires at least that secret version;
it is a floor, not an immutable snapshot. Machine leases do not serialize
standalone Fly.Secret, other Services, or runtime vault writers. A later
writer can advance the shared App vault. Set an explicit deployment input
or version floor when an out-of-band rotation requires a new rollout;
secret changes are not automatically watched.
Mounts
Section titled “Mounts”Pass disks as mounts. Alchemy creates a Volume in the Machine’s
app and region. A Volume attaches to one Machine.
const box = yield* Fly.Machine("Box", { app: Site, region: "iad", image: "nginx:alpine", mounts: [{ path: "/data", sizeGb: 1 }],});From a Service, prefer MountVolume so the
path is part of the binding graph.
Lifecycle
Section titled “Lifecycle”For replicas required to run, reconcile waits until the Machine is
started (waitMachine, bounded). It then waits for configured readiness
checks. With default rolling updates, this happens before the next replica.
The default readiness budget is 60 seconds; set deploy.healthTimeout
for a longer bounded wait. A failed wait stops the rollout with
Fly.ReplicaChecksNotPassing and
the last observed check names, statuses, and output. Later replicas
remain unchanged; earlier updates are not automatically rolled back.
The default rolling strategy updates in place, so a single replica can be
unavailable while it updates. Set deploy: { strategy: "bluegreen" } to
prepare checked replacement Machines before retirement.
For rolling, skipLaunch: true creates or updates config without starting
or checking it. By default, delete force-destroys and waits until gone.
Setting shutdown or enabling blue/green instead cordons reachable
predecessors, signals each with its own persisted shutdown policy, waits
for it to stop, and verifies deletion. A new generation’s shorter timeout
must not shorten the old process’s grace window.
A raw image must handle signals, stop accepting work, and drain requests or jobs. These props do not install the Effect runtime in it. A genuinely unreachable host may require force-deleting an owned stateless predecessor once its replacement is ready. This cannot prove the old work drained. See the deployment and recovery limits.
Alchemy uses native Machine leases. It reports contention rather than stealing a lease. These leases do not lock the whole App or serialize every first deployment. Serialize CI deployments to the same resource. LocalState is not a cross-process lock, and App deletion has no Machine-lease precondition.
autoDestroy: true removes a Machine when its process exits. Blue/green requires
a persistent process and rejects this option, explicit skipLaunch, attached
volumes, and missing readiness checks. It reports unsupported settings rather
than silently switching to rolling. Stop and suspend are supported through the
idle-capacity rules.
Service or Sprite
Section titled “Service or Sprite”Prefer a Service when the program is
Effect. A Service is effectful, supports bindings, and scales with
count. Alchemy builds and pushes the image. Prefer a
Sprite when the sandbox can hibernate —
no parent App, no Docker image.
export default class Api extends Fly.Service<Api>()( "Api", { app: Site, main: import.meta.url, region: "iad", count: 3, port: 3000 }, Effect.gen(function* () { return { fetch: Effect.succeed(HttpServerResponse.text("hello")), }; }),) {}Where next
Section titled “Where next”-
Blue/green deployments — readiness, graceful shutdown, and recovery.
-
Services — bundle an Effect program into a Machine.
-
Regions — where a Machine lives.
-
Volumes — persistent disks.
-
Machinereference — every prop and attribute.