1---
2title: Postgres
3description: Official SSL Postgres in a Project. Bind Railway.ConnectPostgres and query with Drizzle or SQL.
4---
5
6A [`Railway.Postgres`](/providers/railway/postgres) is Postgres as a
7Service: the official
8`ghcr.io/railwayapp-templates/postgres-ssl:16` image, a Volume at
9`/var/lib/postgresql/data`, `POSTGRES_*` / `DATABASE_URL` variables,
10and an optional TCP proxy for the public URL.
11
12Private hostname is `{name}.railway.internal`. From a
13[Service](/railway/compute/services), yield
14[`ConnectPostgres`](/providers/railway/connectpostgres). From a
15laptop, use `publicConnectionUri`.
16
17## Create Postgres
18
19Pass a Project. Alchemy generates a unique name, password, volume,
20and a public TCP proxy.
21
22```typescript
23const site = yield* Railway.Project("Site");
24const db = yield* Railway.Postgres("Db", { project: site });
25```
26
27:::caution[Changing `project` replaces Postgres]
28A new service + volume are created in the new Project. The old
29service and volume are deleted. Data is not copied.
30:::
31
32## Connect from a Service
33
34Yield `ConnectPostgres` in the Service's constructor. Provide
35`ConnectPostgresHttp`. Pass `conn.connectionString` to Drizzle or
36SQL.
37
38```typescript
39import * as Drizzle from "alchemy/Drizzle/Postgres";
40import * as HttpServerResponse from "effect/http/HttpServerResponse";
41
42export default class Api extends Railway.Service<Api>()(
43 "Api",
44 {
45 project: Site,
46 main: import.meta.url,
47 build: { install: ["pg"] },
48 },
49 Effect.gen(function* () {
50 const conn = yield* Railway.ConnectPostgres(Db);
51 const db = yield* Drizzle.Postgres(conn.connectionString);
52 return {
53 fetch: Effect.gen(function* () {
54 const rows = yield* db.execute("select 1 as ok");
55 return HttpServerResponse.json({ rows });
56 }),
57 };
58 }).pipe(Effect.provide(Railway.ConnectPostgresHttp)),
59) {}
60```
61
62`connectionString` is the private URI
63(`{name}.railway.internal:5432`). Both come from `Railway.Postgres`,
64packed into the Service env — not `Config.Redacted`.
65
66To store Railway's `${{Db.DATABASE_URL}}` template instead of a
67resolved URI, pass [`Railway.ref`](/providers/railway/ref)
68(`Railway.ref(Db, "DATABASE_URL")`) as a
69[Variable](/railway/data/variables) `value`.
70
71`build.install: ["pg"]` is required. Rolldown's CJS interop breaks
72`pg.Client` if you bundle it.
73
74## Public TCP
75
76`public` (default `true`) creates a TCP proxy on 5432.
77`publicConnectionUri` is `{domain}:{proxyPort}` for laptop access
78and deploy-time migrations. In-service connections always use the
79private hostname.
80
81```typescript
82const db = yield* Railway.Postgres("Db", {
83 project: site,
84 public: false,
85});
86```
87
88Attach a standalone [`TcpProxy`](/railway/networking#tcp-proxies)
89when you need public TCP on a Redis service, or on Postgres created
90with `public: false`.
91
92## Image
93
94Default is Postgres 16 with SSL. Pass `image` to pin another tag.
95
96```typescript
97const db = yield* Railway.Postgres("Db", {
98 project: site,
99 image: "ghcr.io/railwayapp-templates/postgres-ssl:17",
100});
101```
102
103## Superuser
104
105`user` (default `postgres`) and `database` (default `railway`) are
106create-only. Wrap `password` with `Redacted.make(...)`. If omitted,
107a password is generated on first create.
108
109```typescript
110import * as Redacted from "effect/Redacted";
111
112const db = yield* Railway.Postgres("Db", {
113 project: site,
114 user: "app",
115 database: "app",
116 password: Redacted.make("…"),
117});
118```
119
120## Module-scope declarations
121
122Resource-valued props accept the resource or an Effect producing it.
123
124```typescript
125// src/db.ts
126import * as Railway from "alchemy/Railway";
127
128export const Site = Railway.Project("Site");
129export const Db = Railway.Postgres("Db", { project: Site });
130```
131
132## Where next
133
134[Regions](/railway/compute/regions) lists codes.
135[Services](/railway/compute/services) is the container that binds
136the cluster.
137[MySQL](/railway/data/mysql) and [Mongo](/railway/data/mongo) are the
138same shape for those engines.
139[Drizzle on Postgres](/sql/drizzle/postgres) is the schema-to-query
140flow.
141[Variables](/railway/data/variables) covers `Config.Redacted` and
142`Railway.ref`.
143The [`Postgres` reference](/providers/railway/postgres) lists every
144prop.
145The [`ConnectPostgres` reference](/providers/railway/connectpostgres)
146is the runtime binding.
147[Example: railway-service](https://github.com/alchemy-run/alchemy/tree/main/examples/railway-service)
148is the complete runnable project.