Machine
Source:
src/Fly/Machine.ts
A Fly.Machine is a Firecracker VM running a container image.
Prefer a Service when the program is Effect. A Service is
effectful, supports bindings, and scales with count. Alchemy builds
and pushes the image. Use Fly.Machine when you already have an image.
Prefer a Service
Section titled “Prefer a Service”Declare a Service when you own the program. Alchemy bundles
main, builds linux/amd64, and pushes to registry.fly.io.
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")), }; }),) {}Launch a Machine
Section titled “Launch a Machine”The parent is an App. Pin a region and an image. Guest
defaults to shared-cpu 1× / 256 MB. image updates in place.
const web = yield* Fly.Machine("Web", { app: Site, region: "iad", image: "nginx:alpine",});A stable name
Section titled “A stable name”Machine names are unique per App. Omit name and Alchemy generates
one from the stack, stage, and logical ID.
const web = yield* Fly.Machine("Web", { app: Site, name: "web", region: "iad", image: "nginx:alpine",});Region
Section titled “Region”Fly Machines live in a region. Default is iad. See
Regions for the list of codes.
const web = yield* Fly.Machine("Web", { app: Site, region: "ewr", image: "nginx:alpine",});Guest size
Section titled “Guest size”guest is CPU kind, CPU count, and memory. Default is shared-cpu,
1 CPU, 256 MB. Guest updates in place.
const web = yield* Fly.Machine("Web", { app: Site, region: "iad", image: "nginx:alpine", guest: { cpuKind: "shared", cpus: 1, memoryMb: 256 },});Set gpuKind and gpus on guest when the Machine should have a
GPU.
const worker = yield* Fly.Machine("Worker", { app: Site, region: "iad", image: "my-gpu-image:tag", guest: { cpuKind: "performance", cpus: 2, memoryMb: 4096, gpuKind: "a10", gpus: 1, },});Environment variables
Section titled “Environment variables”env is merged onto the Machine. Fly also injects App
Secret values as env vars unless the Machine skips secrets.
const worker = yield* Fly.Machine("Worker", { app: Site, region: "iad", image: "my-image:tag", env: { LOG_LEVEL: "info" },});Publish a proxy service
Section titled “Publish a proxy service”services publishes ports on Fly’s proxy. {app}.fly.dev over IPv4
still needs an IpAssignment on the parent App. url is
https://{appName}.fly.dev when a proxy service is configured.
Handlers are http, tls, pg_tls, and similar. Set forceHttps
to redirect HTTP to HTTPS. Use startPort / endPort for a
published range.
Omit services (or pass []) for a process that should not be
reachable from the internet.
const web = yield* Fly.Machine("Web", { app: Site, region: "iad", image: "nginx:alpine", services: [ { protocol: "tcp", internalPort: 80, ports: [ { port: 80, handlers: ["http"], forceHttps: true }, { port: 443, handlers: ["tls", "http"] }, ], }, ],});Autostart and autostop
Section titled “Autostart and autostop”autostart starts the Machine when a request arrives. autostop is
"off", "stop", "suspend", or a boolean. minMachinesRunning
keeps that many Machines up for the service.
Autostop only stops Machines that already exist. It does not mint new ones. Yield more Machine resources to size the pool.
const web = yield* Fly.Machine("Web", { app: Site, region: "iad", image: "nginx:alpine", services: [ { protocol: "tcp", internalPort: 80, autostart: true, autostop: "stop", minMachinesRunning: 0, ports: [{ port: 80, handlers: ["http"] }], }, ],});Scale up
Section titled “Scale up”Each Machine resource is one VM. Yield another Machine to add
capacity. Fly’s proxy load-balances published services across
them.
A Service still scales with count. That is one program,
many Machines.
const web1 = yield* Fly.Machine("Web1", { app: Site, region: "iad", image: "nginx:alpine", services: [ { protocol: "tcp", internalPort: 80, ports: [{ port: 80, handlers: ["http"] }], }, ],});
const web2 = yield* Fly.Machine("Web2", { app: Site, region: "iad", image: "nginx:alpine", services: [ { protocol: "tcp", internalPort: 80, ports: [{ port: 80, handlers: ["http"] }], }, ],});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",});Attach a disk
Section titled “Attach a disk”Pass disks as mounts. Alchemy creates a Volume in the Machine’s
app and region. A Volume attaches to one Machine. There is no
standalone Volume resource.
sizeGb can grow in place. Shrinking is not supported. Encryption,
filesystem type, snapshotId, and sourceVolumeId are create-only.
See MountVolume for the full disk spec. From a Service,
prefer MountVolume so the path is part of the binding graph.
const box = yield* Fly.Machine("Box", { app: Site, region: "iad", image: "postgres:16", mounts: [{ path: "/data", sizeGb: 10 }],});init overrides cmd, entrypoint, exec, swap, and TTY. Updates
in place.
const box = yield* Fly.Machine("Box", { app: Site, region: "iad", image: "postgres:16", init: { cmd: ["postgres", "-c", "shared_buffers=256MB"] },});Restart policy
Section titled “Restart policy”restart.policy is "no", "always", "on-failure", or
"spot-price". maxRetries applies when the policy is
"on-failure". Updates in place.
const worker = yield* Fly.Machine("Worker", { app: Site, region: "iad", image: "my-image:tag", restart: { policy: "always" },});Destroy on exit
Section titled “Destroy on exit”autoDestroy: true tears the Machine down when its main process
exits. Default is false.
const job = yield* Fly.Machine("Job", { app: Site, region: "iad", image: "my-job:tag", autoDestroy: true, restart: { policy: "no" },});Skip launch
Section titled “Skip launch”skipLaunch: true creates or updates the config without starting
the Machine. Default is false. Reconcile otherwise waits until
the Machine is started.
const web = yield* Fly.Machine("Web", { app: Site, region: "iad", image: "nginx:alpine", skipLaunch: true,});Metadata
Section titled “Metadata”User keys on metadata merge with Alchemy ownership keys
(alchemy.stack, alchemy.stage, alchemy.id, alchemy.type,
alchemy.replica). Those ownership keys are always written so
list() can find owned Machines. Fly Apps have no labels.
const web = yield* Fly.Machine("Web", { app: Site, region: "iad", image: "nginx:alpine", metadata: { role: "edge" },});Secrets version
Section titled “Secrets version”minSecretsVersion waits until the Machine has seen at least that
App secrets version. Use it after rotating a Secret if the
process must start with the new value.
const web = yield* Fly.Machine("Web", { app: Site, region: "iad", image: "nginx:alpine", minSecretsVersion: 2,});