Skip to content

Commit 7ef63f7

Browse files
harshil1712Oxyjun
andauthored
Update Postgres tutorial to use node-postgres (#23353)
* Update Postgres tutorial to use node-postgres * Update src/content/docs/workers/tutorials/postgres/index.mdx --------- Co-authored-by: Jun Lee <[email protected]>
1 parent c4dd1c5 commit 7ef63f7

File tree

1 file changed

+94
-65
lines changed
  • src/content/docs/workers/tutorials/postgres

1 file changed

+94
-65
lines changed

src/content/docs/workers/tutorials/postgres/index.mdx

Lines changed: 94 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
updated: 2024-08-23
2+
updated: 2025-07-01
33
difficulty: Beginner
44
pcx_content_type: tutorial
55
title: Connect to a PostgreSQL database with Cloudflare Workers
@@ -62,11 +62,17 @@ cd postgres-tutorial
6262

6363
## 2. Add the PostgreSQL connection library
6464

65-
To connect to a PostgreSQL database, you will need the `postgres` library. In your Worker application directory, run the following command to install the library:
65+
To connect to a PostgreSQL database, you will need the `pg` library. In your Worker application directory, run the following command to install the library:
6666

67-
<PackageManagers pkg="postgres" />
67+
<PackageManagers pkg="pg" />
6868

69-
Make sure you are using `postgres` (`Postgres.js`) version `3.4.4` or higher. `Postgres.js` is compatible with both Pages and Workers.
69+
Next, install the TypeScript types for the `pg` library to enable type checking and autocompletion in your TypeScript code:
70+
71+
<PackageManagers pkg="@types/pg" dev />
72+
73+
:::note
74+
Make sure you are using `pg` (`node-postgres`) version `8.16.3` or higher.
75+
:::
7076

7177
## 3. Configure the connection to the PostgreSQL database
7278

@@ -115,7 +121,7 @@ Configure each database parameter as an [environment variable](/workers/configur
115121
DB_USERNAME = "postgres"
116122
# Set your password by creating a secret so it is not stored as plain text
117123
DB_HOST = "ep-aged-sound-175961.us-east-2.aws.neon.tech"
118-
DB_PORT = "5432"
124+
DB_PORT = 5432
119125
DB_NAME = "productsdb"
120126
```
121127

@@ -138,27 +144,34 @@ npx wrangler secret put DB_PASSWORD
138144
Open your Worker's main file (for example, `worker.ts`) and import the `Client` class from the `pg` library:
139145

140146
```typescript
141-
import postgres from "postgres";
147+
import { Client } from "pg";
142148
```
143149

144150
In the `fetch` event handler, connect to the PostgreSQL database using your chosen method, either the connection string or the explicit parameters.
145151

146152
### Use a connection string
147153

148154
```typescript
149-
const sql = postgres(env.DB_URL);
155+
// create a new Client instance using the connection string
156+
const sql = new Client({ connectionString: env.DB_URL });
157+
// connect to the PostgreSQL database
158+
await sql.connect();
150159
```
151160

152161
### Set explicit parameters
153162

154163
```typescript
155-
const sql = postgres({
164+
// create a new Client instance using explicit parameters
165+
const sql = new Client({
156166
username: env.DB_USERNAME,
157167
password: env.DB_PASSWORD,
158168
host: env.DB_HOST,
159169
port: env.DB_PORT,
160170
database: env.DB_NAME,
171+
ssl: true, // Enable SSL for secure connections
161172
});
173+
// connect to the PostgreSQL database
174+
await sql.connect();
162175
```
163176

164177
## 5. Interact with the products database
@@ -183,30 +196,33 @@ CREATE TABLE products (
183196
Replace the existing code in your `worker.ts` file with the following code:
184197

185198
```typescript
186-
import postgres from "postgres";
199+
import { Client } from "pg";
187200

188201
export default {
189202
async fetch(request, env, ctx): Promise<Response> {
190-
const sql = postgres(env.DB_URL, {
191-
// Workers limit the number of concurrent external connections, so be sure to limit
192-
// the size of the local connection pool that postgres.js may establish.
193-
max: 5,
194-
195-
// If you are using array types in your Postgres schema, it is necessary to fetch
196-
// type information to correctly de/serialize them. However, if you are not using
197-
// those, disabling this will save you an extra round-trip every time you connect.
198-
fetch_types: false,
203+
// Create a new Client instance using the connection string
204+
// or explicit parameters as shown in the previous steps.
205+
// Here, we are using the connection string method.
206+
const sql = new Client({
207+
connectionString: env.DB_URL,
199208
});
200-
201-
// Query the products table
202-
const result = await sql`SELECT * FROM products;`;
203-
204-
// Return the result as JSON
205-
const resp = new Response(JSON.stringify(result), {
206-
headers: { "Content-Type": "application/json" },
207-
});
208-
209-
return resp;
209+
try {
210+
// Connect to the PostgreSQL database
211+
await sql.connect();
212+
213+
// Query the products table
214+
const result = await sql.query("SELECT * FROM products");
215+
216+
// Return the result as JSON
217+
return new Response(JSON.stringify(result.rows), {
218+
headers: {
219+
"Content-Type": "application/json",
220+
},
221+
});
222+
} finally {
223+
// Clean up the client connection
224+
await sql.end();
225+
}
210226
},
211227
} satisfies ExportedHandler<Env>;
212228
```
@@ -233,47 +249,60 @@ Assume the `products` table has the following columns: `id`, `name`, `descriptio
233249

234250
Add the following code snippet inside the `fetch` event handler in your `worker.ts` file, before the existing query code:
235251

236-
```typescript {9-32}
237-
import postgres from "postgres";
252+
```typescript {15-39}
253+
import { Client } from "pg";
238254

239255
export default {
240256
async fetch(request, env, ctx): Promise<Response> {
241-
const sql = postgres(env.DB_URL);
242-
243-
const url = new URL(request.url);
244-
if (request.method === "POST" && url.pathname === "/products") {
245-
// Parse the request's JSON payload
246-
const productData = await request.json();
247-
248-
// Insert the new product into the database
249-
const values = {
250-
name: productData.name,
251-
description: productData.description,
252-
price: productData.price,
253-
};
254-
const insertResult = await sql`
255-
INSERT INTO products ${sql(values)}
256-
RETURNING *
257-
`;
258-
259-
// Return the inserted row as JSON
260-
const insertResp = new Response(JSON.stringify(insertResult), {
261-
headers: { "Content-Type": "application/json" },
257+
// Create a new Client instance using the connection string
258+
// or explicit parameters as shown in the previous steps.
259+
// Here, we are using the connection string method.
260+
const sql = new Client({
261+
connectionString: env.DB_URL,
262+
});
263+
try {
264+
// Connect to the PostgreSQL database
265+
await sql.connect();
266+
267+
const url = new URL(request.url);
268+
if (request.method === "POST" && url.pathname === "/products") {
269+
// Parse the request's JSON payload
270+
const productData = (await request.json()) as {
271+
name: string;
272+
description: string;
273+
price: number;
274+
};
275+
276+
const name = productData.name,
277+
description = productData.description,
278+
price = productData.price;
279+
280+
// Insert the new product into the products table
281+
const insertResult = await sql.query(
282+
`INSERT INTO products(name, description, price) VALUES($1, $2, $3)
283+
RETURNING *`,
284+
[name, description, price],
285+
);
286+
287+
// Return the inserted row as JSON
288+
return new Response(JSON.stringify(insertResult.rows), {
289+
headers: { "Content-Type": "application/json" },
290+
});
291+
}
292+
293+
// Query the products table
294+
const result = await sql.query("SELECT * FROM products");
295+
296+
// Return the result as JSON
297+
return new Response(JSON.stringify(result.rows), {
298+
headers: {
299+
"Content-Type": "application/json",
300+
},
262301
});
263-
264-
// Clean up the client
265-
return insertResp;
302+
} finally {
303+
// Clean up the client connection
304+
await sql.end();
266305
}
267-
268-
// Query the products table
269-
const result = await sql`SELECT * FROM products;`;
270-
271-
// Return the result as JSON
272-
const resp = new Response(JSON.stringify(result), {
273-
headers: { "Content-Type": "application/json" },
274-
});
275-
276-
return resp;
277306
},
278307
} satisfies ExportedHandler<Env>;
279308
```
@@ -343,7 +372,7 @@ Replace your existing connection string in your Worker code with the Hyperdrive
343372
```js {3-3}
344373
export default {
345374
async fetch(request, env, ctx): Promise<Response> {
346-
const sql = postgres(env.HYPERDRIVE.connectionString)
375+
const sql = new Client({connectionString: env.HYPERDRIVE.connectionString})
347376

348377
const url = new URL(request.url);
349378

0 commit comments

Comments
 (0)