diff --git a/src/content/docs/workers/tutorials/postgres/index.mdx b/src/content/docs/workers/tutorials/postgres/index.mdx
index 4e913a87dbe70d8..c6bf48c42d055d6 100644
--- a/src/content/docs/workers/tutorials/postgres/index.mdx
+++ b/src/content/docs/workers/tutorials/postgres/index.mdx
@@ -1,5 +1,5 @@
---
-updated: 2024-08-23
+updated: 2025-07-01
difficulty: Beginner
pcx_content_type: tutorial
title: Connect to a PostgreSQL database with Cloudflare Workers
@@ -63,11 +63,17 @@ cd postgres-tutorial
## 2. Add the PostgreSQL connection library
-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:
+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:
-
+
-Make sure you are using `postgres` (`Postgres.js`) version `3.4.4` or higher. `Postgres.js` is compatible with both Pages and Workers.
+Next, install the TypeScript types for the `pg` library to enable type checking and autocompletion in your TypeScript code:
+
+
+
+:::note
+Make sure you are using `pg` (`node-postgres`) version `8.16.3` or higher.
+:::
## 3. Configure the connection to the PostgreSQL database
@@ -116,7 +122,7 @@ Configure each database parameter as an [environment variable](/workers/configur
DB_USERNAME = "postgres"
# Set your password by creating a secret so it is not stored as plain text
DB_HOST = "ep-aged-sound-175961.us-east-2.aws.neon.tech"
-DB_PORT = "5432"
+DB_PORT = 5432
DB_NAME = "productsdb"
```
@@ -139,7 +145,7 @@ npx wrangler secret put DB_PASSWORD
Open your Worker's main file (for example, `worker.ts`) and import the `Client` class from the `pg` library:
```typescript
-import postgres from "postgres";
+import { Client } from "pg";
```
In the `fetch` event handler, connect to the PostgreSQL database using your chosen method, either the connection string or the explicit parameters.
@@ -147,19 +153,26 @@ In the `fetch` event handler, connect to the PostgreSQL database using your chos
### Use a connection string
```typescript
-const sql = postgres(env.DB_URL);
+// create a new Client instance using the connection string
+const sql = new Client({ connectionString: env.DB_URL });
+// connect to the PostgreSQL database
+await sql.connect();
```
### Set explicit parameters
```typescript
-const sql = postgres({
+// create a new Client instance using explicit parameters
+const sql = new Client({
username: env.DB_USERNAME,
password: env.DB_PASSWORD,
host: env.DB_HOST,
port: env.DB_PORT,
database: env.DB_NAME,
+ ssl: true, // Enable SSL for secure connections
});
+// connect to the PostgreSQL database
+await sql.connect();
```
## 5. Interact with the products database
@@ -184,30 +197,33 @@ CREATE TABLE products (
Replace the existing code in your `worker.ts` file with the following code:
```typescript
-import postgres from "postgres";
+import { Client } from "pg";
export default {
async fetch(request, env, ctx): Promise {
- const sql = postgres(env.DB_URL, {
- // Workers limit the number of concurrent external connections, so be sure to limit
- // the size of the local connection pool that postgres.js may establish.
- max: 5,
-
- // If you are using array types in your Postgres schema, it is necessary to fetch
- // type information to correctly de/serialize them. However, if you are not using
- // those, disabling this will save you an extra round-trip every time you connect.
- fetch_types: false,
+ // Create a new Client instance using the connection string
+ // or explicit parameters as shown in the previous steps.
+ // Here, we are using the connection string method.
+ const sql = new Client({
+ connectionString: env.DB_URL,
});
-
- // Query the products table
- const result = await sql`SELECT * FROM products;`;
-
- // Return the result as JSON
- const resp = new Response(JSON.stringify(result), {
- headers: { "Content-Type": "application/json" },
- });
-
- return resp;
+ try {
+ // Connect to the PostgreSQL database
+ await sql.connect();
+
+ // Query the products table
+ const result = await sql.query("SELECT * FROM products");
+
+ // Return the result as JSON
+ return new Response(JSON.stringify(result.rows), {
+ headers: {
+ "Content-Type": "application/json",
+ },
+ });
+ } finally {
+ // Clean up the client connection
+ await sql.end();
+ }
},
} satisfies ExportedHandler;
```
@@ -234,47 +250,60 @@ Assume the `products` table has the following columns: `id`, `name`, `descriptio
Add the following code snippet inside the `fetch` event handler in your `worker.ts` file, before the existing query code:
-```typescript {9-32}
-import postgres from "postgres";
+```typescript {15-39}
+import { Client } from "pg";
export default {
async fetch(request, env, ctx): Promise {
- const sql = postgres(env.DB_URL);
-
- const url = new URL(request.url);
- if (request.method === "POST" && url.pathname === "/products") {
- // Parse the request's JSON payload
- const productData = await request.json();
-
- // Insert the new product into the database
- const values = {
- name: productData.name,
- description: productData.description,
- price: productData.price,
- };
- const insertResult = await sql`
- INSERT INTO products ${sql(values)}
- RETURNING *
- `;
-
- // Return the inserted row as JSON
- const insertResp = new Response(JSON.stringify(insertResult), {
- headers: { "Content-Type": "application/json" },
+ // Create a new Client instance using the connection string
+ // or explicit parameters as shown in the previous steps.
+ // Here, we are using the connection string method.
+ const sql = new Client({
+ connectionString: env.DB_URL,
+ });
+ try {
+ // Connect to the PostgreSQL database
+ await sql.connect();
+
+ const url = new URL(request.url);
+ if (request.method === "POST" && url.pathname === "/products") {
+ // Parse the request's JSON payload
+ const productData = (await request.json()) as {
+ name: string;
+ description: string;
+ price: number;
+ };
+
+ const name = productData.name,
+ description = productData.description,
+ price = productData.price;
+
+ // Insert the new product into the products table
+ const insertResult = await sql.query(
+ `INSERT INTO products(name, description, price) VALUES($1, $2, $3)
+ RETURNING *`,
+ [name, description, price],
+ );
+
+ // Return the inserted row as JSON
+ return new Response(JSON.stringify(insertResult.rows), {
+ headers: { "Content-Type": "application/json" },
+ });
+ }
+
+ // Query the products table
+ const result = await sql.query("SELECT * FROM products");
+
+ // Return the result as JSON
+ return new Response(JSON.stringify(result.rows), {
+ headers: {
+ "Content-Type": "application/json",
+ },
});
-
- // Clean up the client
- return insertResp;
+ } finally {
+ // Clean up the client connection
+ await sql.end();
}
-
- // Query the products table
- const result = await sql`SELECT * FROM products;`;
-
- // Return the result as JSON
- const resp = new Response(JSON.stringify(result), {
- headers: { "Content-Type": "application/json" },
- });
-
- return resp;
},
} satisfies ExportedHandler;
```
@@ -344,7 +373,7 @@ Replace your existing connection string in your Worker code with the Hyperdrive
```js {3-3}
export default {
async fetch(request, env, ctx): Promise {
- const sql = postgres(env.HYPERDRIVE.connectionString)
+ const sql = new Client({connectionString: env.HYPERDRIVE.connectionString})
const url = new URL(request.url);