Skip to content

Postgres

A Fly.Postgres is a Managed Postgres (MPG) cluster. It is billed. Do not wrap unmanaged fly postgres.

Create the cluster, pass migrations the same way you would on Neon or PlanetScale, then bind ConnectPostgres on a Service. Pass conn.connectionString to Drizzle.Postgres or SQL.Postgres.

region is required. The cluster is regional. An App is global. Alchemy generates a unique name unless you pass one.

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

Alchemy defaults compute to iad. Pass another code to put the cluster somewhere else.

Yield ConnectPostgres in Service init. Provide ConnectPostgresHttp. Pass the connection string to Drizzle or SQL.

import * as Drizzle from "alchemy/Drizzle/Postgres";
import * as HttpServerResponse from "effect/unstable/http/HttpServerResponse";
export default class Api extends Fly.Service<Api>()(
"Api",
{ app: Site, main: import.meta.url, port: 3000 },
Effect.gen(function* () {
const conn = yield* Fly.ConnectPostgres(Db);
const db = yield* Drizzle.Postgres(conn.connectionString);
return {
fetch: Effect.gen(function* () {
const rows = yield* db.execute("select 1 as ok");
return HttpServerResponse.json({ rows });
}),
};
}).pipe(Effect.provide(Fly.ConnectPostgresHttp)),
) {}

connectionString is the cluster’s pooled PgBouncer URI Output. directConnectionString is the direct URI. Both come from Fly.Postgres, packed into the Service env — not Config.redacted.

Pass a directory, { dir, table? }, or a Drizzle.Schema resource. Alchemy applies pending files on deploy over the direct URI and records them in __alchemy_migrations.

const schema = yield* Drizzle.Schema("app-schema", {
schema: "./src/schema.ts",
out: "./migrations",
});
const db = yield* Fly.Postgres("Db", {
region: "iad",
migrations: schema,
});
const db = yield* Fly.Postgres("Db", {
region: "iad",
migrations: "./migrations",
importFiles: ["./seed.sql"],
});

MPG is on the org private network. Deploy-time apply needs a route to that network.

plan is the hardware size: basic, starter, launch, scale, performance. Default is basic.

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

volumeSizeGb is the initial disk. Fly defaults to 10 GB.

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

postgis: true enables PostGIS at create.

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

Regions lists codes. Default is iad. Services is the always-on Machine that binds the cluster. Drizzle on Postgres is the schema-to-query flow. Secrets covers Config.redacted for values from .env. The Postgres reference lists every prop. The ConnectPostgres reference is the runtime binding. Example: fly-postgres is the complete runnable project.