1---
2title: Postgres
3description: A billed Managed Postgres cluster. Bind Fly.ConnectPostgres and query with Drizzle or SQL.
4---
5
6A [`Fly.Postgres`](/providers/fly/postgres) is a Managed Postgres
7(MPG) cluster. It is billed. Do not wrap unmanaged `fly postgres`.
8
9Create the cluster, pass `migrations` the same way you would on
10Neon or PlanetScale, then bind
11[`ConnectPostgres`](/providers/fly/connectpostgres) on a
12[Service](/fly/compute/services). Pass
13`conn.connectionString` to `Drizzle.Postgres` or `SQL.Postgres`.
14
15## Create a cluster
16
17`region` is required. The cluster is regional. An
18[App](/fly/compute/apps) is global. Alchemy generates a unique name
19unless you pass one.
20
21```typescript
22const db = yield* Fly.Postgres("Db", {
23 region: "iad",
24});
25```
26
27Alchemy defaults compute to [`iad`](/fly/compute/regions). Pass
28another code to put the cluster somewhere else.
29
30:::caution[Billed]
31Managed Postgres is billed. Basic is about $38 per month.
32:::
33
34:::caution[Changing `region` replaces the cluster]
35A new cluster is created in the new region. The old cluster is
36deleted. Data is not copied.
37:::
38
39## Connect from a Service
40
41Yield `ConnectPostgres` in the Service's constructor. Provide
42`ConnectPostgresHttp`. Pass the connection string to Drizzle or
43SQL.
44
45```typescript
46import * as Drizzle from "alchemy/Drizzle/Postgres";
47import * as HttpServerResponse from "effect/http/HttpServerResponse";
48
49export default class Api extends Fly.Service<Api>()(
50 "Api",
51 { main: import.meta.url, port: 3000 },
52 Effect.gen(function* () {
53 const conn = yield* Fly.ConnectPostgres(Db);
54 const db = yield* Drizzle.Postgres(conn.connectionString);
55 return {
56 fetch: Effect.gen(function* () {
57 const rows = yield* db.execute("select 1 as ok");
58 return HttpServerResponse.json({ rows });
59 }),
60 };
61 }).pipe(Effect.provide(Fly.ConnectPostgresHttp)),
62) {}
63```
64
65`connectionString` is the cluster's pooled PgBouncer URI Output.
66`directConnectionString` is the direct URI. Both come from
67`Fly.Postgres`, packed into the Service env — not `Config.Redacted`.
68
69## Migrations
70
71Pass a directory, `{ dir, table? }`, or a `Drizzle.Schema`
72resource. Alchemy applies pending files on deploy over the direct
73URI and records them in `__alchemy_migrations`.
74
75```typescript
76const schema = yield* Drizzle.Schema("app-schema", {
77 schema: "./src/schema.ts",
78 out: "./migrations",
79});
80
81const db = yield* Fly.Postgres("Db", {
82 region: "iad",
83 migrations: schema,
84});
85```
86
87```typescript
88const db = yield* Fly.Postgres("Db", {
89 region: "iad",
90 migrations: "./migrations",
91 importFiles: ["./seed.sql"],
92});
93```
94
95MPG is on the org private network. Deploy-time apply needs a
96route to that network.
97
98## Plan
99
100`plan` is the hardware size: `basic`, `starter`, `launch`,
101`scale`, `performance`. Default is `basic`.
102
103```typescript
104const db = yield* Fly.Postgres("Db", {
105 region: "iad",
106 plan: "starter",
107});
108```
109
110:::note[Create-only]
111Changing `plan` later is ignored. Fly has no cluster update API.
112:::
113
114## Volume size
115
116`volumeSizeGb` is the initial disk. Fly defaults to 10 GB.
117
118```typescript
119const db = yield* Fly.Postgres("Db", {
120 region: "iad",
121 volumeSizeGb: 20,
122});
123```
124
125:::note[Create-only]
126Changing `volumeSizeGb` later is ignored.
127:::
128
129## PostGIS
130
131`postgis: true` enables PostGIS at create.
132
133```typescript
134const db = yield* Fly.Postgres("Db", {
135 region: "iad",
136 postgis: true,
137});
138```
139
140:::note[Create-only]
141Flipping `postgis` later is ignored.
142:::
143
144## Where next
145
146[Regions](/fly/compute/regions) lists codes. Default is `iad`.
147[Services](/fly/compute/services) is the always-on Machine that
148binds the cluster.
149[Drizzle on Postgres](/sql/drizzle/postgres) is the schema-to-query
150flow.
151[Secrets](/fly/data/secrets) covers `Config.Redacted` for values
152from `.env`.
153The [`Postgres` reference](/providers/fly/postgres) lists every
154prop.
155The [`ConnectPostgres` reference](/providers/fly/connectpostgres)
156is the runtime binding.
157[Example: fly-postgres](https://github.com/alchemy-run/alchemy/tree/main/examples/fly-postgres)
158is the complete runnable project.