Skip to content

Commit 931443d

Browse files
committed
Update Postgres tutorial to use node-postgres
1 parent 14e5493 commit 931443d

File tree

1 file changed

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

1 file changed

+92
-65
lines changed

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

Lines changed: 92 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
@@ -63,11 +63,15 @@ cd postgres-tutorial
6363

6464
## 2. Add the PostgreSQL connection library
6565

66-
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:
66+
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:
6767

68-
<PackageManagers pkg="postgres" />
68+
<PackageManagers pkg="pg" />
6969

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

7276
## 3. Configure the connection to the PostgreSQL database
7377

@@ -116,7 +120,7 @@ Configure each database parameter as an [environment variable](/workers/configur
116120
DB_USERNAME = "postgres"
117121
# Set your password by creating a secret so it is not stored as plain text
118122
DB_HOST = "ep-aged-sound-175961.us-east-2.aws.neon.tech"
119-
DB_PORT = "5432"
123+
DB_PORT = 5432
120124
DB_NAME = "productsdb"
121125
```
122126

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

141145
```typescript
142-
import postgres from "postgres";
146+
import { Client } from "pg";
143147
```
144148

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

147151
### Use a connection string
148152

149153
```typescript
150-
const sql = postgres(env.DB_URL);
154+
// create a new Client instance using the connection string
155+
const sql = new Client({ connectionString: env.DB_URL });
156+
// connect to the PostgreSQL database
157+
await sql.connect();
151158
```
152159

153160
### Set explicit parameters
154161

155162
```typescript
156-
const sql = postgres({
163+
// create a new Client instance using explicit parameters
164+
const sql = new Client({
157165
username: env.DB_USERNAME,
158166
password: env.DB_PASSWORD,
159167
host: env.DB_HOST,
160168
port: env.DB_PORT,
161169
database: env.DB_NAME,
170+
ssl: true, // Enable SSL for secure connections
162171
});
172+
// connect to the PostgreSQL database
173+
await sql.connect();
163174
```
164175

165176
## 5. Interact with the products database
@@ -184,30 +195,33 @@ CREATE TABLE products (
184195
Replace the existing code in your `worker.ts` file with the following code:
185196

186197
```typescript
187-
import postgres from "postgres";
198+
import { Client } from "pg";
188199

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

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

237-
```typescript {9-32}
238-
import postgres from "postgres";
251+
```typescript {15-39}
252+
import { Client } from "pg";
239253

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

349376
const url = new URL(request.url);
350377

0 commit comments

Comments
 (0)