Skip to content

Regions

A region is a Fly.io datacenter. Machines, Volumes, Postgres clusters, and a Redis primary live in one. An App is global. It is not pinned to a region.

Alchemy defaults to iad (Ashburn, Virginia). Pass region to put a Service, Machine, or Postgres cluster somewhere else.

export default class Api extends Fly.Service<Api>()(
"Api",
{ app: Site, main: import.meta.url, region: "lhr", port: 3000 },
Effect.gen(function* () {
return {
fetch: Effect.succeed(HttpServerResponse.text("hello")),
};
}),
) {}

count extra Machines stay in that same region.

const web = yield* Fly.Machine("Web", {
app: Site,
region: "syd",
image: "nginx:alpine",
});

Each Machine resource is one VM in one region. To run in two regions, declare two Machines.

A Volume is created in the parent Service or Machine’s region. It cannot move and cannot attach to a Machine in another region.

Restore into a new region from a VolumeSnapshot with snapshotId on the mount.

Put two Services on the same App with different region values. Each Service is its own file. Fly’s Anycast proxy sends a request to a nearby Machine that published the service. They share {app}.fly.dev.

src/api-iad.ts
export default class ApiIad extends Fly.Service<ApiIad>()(
"ApiIad",
{ app: Site, main: import.meta.url, region: "iad", port: 3000 },
Effect.gen(function* () {
return {
fetch: Effect.succeed(HttpServerResponse.text("hello")),
};
}),
) {}

Same program, London:

src/api-lhr.ts
export default class ApiLhr extends Fly.Service<ApiLhr>()(
"ApiLhr",
{ app: Site, main: import.meta.url, region: "lhr", port: 3000 },
Effect.gen(function* () {
return {
fetch: Effect.succeed(HttpServerResponse.text("hello")),
};
}),
) {}

Yield both in the Stack.

Fly sets FLY_REGION on the Machine. Read it in a Service with Config.

import * as Config from "effect/Config";
const region = yield* Config.string("FLY_REGION");

Codes are three letters. This list is what Fly published as of August 2026. Run fly platform regions or see Fly’s regions for the live set.

Code Location
ams Amsterdam, Netherlands
arn Stockholm, Sweden
bom Mumbai, India
cdg Paris, France
dfw Dallas, Texas (US)
ewr Secaucus, NJ (US)
fra Frankfurt, Germany
gru São Paulo, Brazil
iad Ashburn, Virginia (US)
jnb Johannesburg, South Africa
lax Los Angeles, California (US)
lhr London, United Kingdom
nrt Tokyo, Japan
ord Chicago, Illinois (US)
sin Singapore
sjc San Jose, California (US)
syd Sydney, Australia
yyz Toronto, Canada

A dedicated IpAssignment can take region too. Shared Anycast (shared_v4) ignores it.

The cluster lives in one region. Pass region on Fly.Postgres, not on the App.

const db = yield* Fly.Postgres("Db", {
region: "iad",
});

Fly.Redis takes primaryRegion. Default is iad. Read replicas are extra regions on readRegions.

const cache = yield* Fly.Redis("Cache", {
primaryRegion: "iad",
readRegions: ["sjc"],
});

Services pin region on the class. Machines pin it on the resource. Volumes follow the parent. Postgres is a billed cluster in one region. Redis pins primaryRegion.