JavaScript
This guide describes how to create a SerenDB project and connect to it from a Node.js application using popular Postgres clients:
node-postgres (pg): The most widely-used and robust driver for Node.js.
Postgres.js: A modern, high-performance driver with a focus on a great developer experience.
@serenorg/serverless: The SerenDB serverless driver, which connects over HTTP and is optimized for serverless and edge environments.
You'll learn how to connect to your SerenDB database from a JavaScript application and perform basic Create, Read, Update, and Delete (CRUD) operations.
Your database connection string contains sensitive credentials and must **never** be exposed in client-side javascript code (e.g., in a browser). All database operations should be handled in a secure, server-side environment like a Node.js backend or a serverless function.
Prerequisites
Create a SerenDB project
If you do not have one already, create a SerenDB project.
Navigate to the Projects page in the SerenDB Console.
Click New Project.
Specify your project settings and click Create Project.
Your project is created with a ready-to-use database named neondb. In the following steps, you will connect to this database from your JavaScript application.
Create a Node.js project
For your Node.js project, create a project directory, initialize it with npm, and install the required libraries.
Create a project directory and change into it.
mkdir neon-nodejs-quickstart cd neon-nodejs-quickstartOpen the directory in your preferred code editor (e.g., VS Code).
Initialize a new Node.js project. The
-yflag accepts all the default settings.npm init -yInstall the required libraries using
npm.<CodeTabs labels={["node-postgres (pg)", "SerenDB serverless driver", "postgres.js"]}>
npm install pg dotenvnpm install @serenorg/serverless dotenvnpm install postgres dotenvOpen your
package.jsonfile and add the following line into it:{ // other properties "type": "module" }This allows you to use ES module syntax (
import) in your JavaScript files.
Store your SerenDB connection string
Create a file named .env in your project's root directory. This file will securely store your database connection string, keeping your credentials separate from your source code.
In the SerenDB Console, select your project on the Dashboard.
Click Connect on your Project Dashboard to open the Connect to your database modal.

Select Node.js from the connection string dropdown and copy the full connection string.
Add the connection string to your
.envfile as shown below.DATABASE_URL="postgresql://[user]:[password]@[seren_hostname]/[dbname]?sslmode=require&channel_binding=require"Replace
[user],[password],[seren_hostname], and[dbname]with your actual database credentials.
Examples
This section provides example JavaScript scripts that demonstrate how to connect to your SerenDB database and perform basic operations such as creating a table, reading data, updating data, and deleting data.
Create a table and insert data
In your project directory, create a file named create_table.js and add the code for your preferred library. This script connects to your SerenDB database, creates a table named books, and inserts some sample data into it.
<CodeTabs labels={["node-postgres (pg)", "SerenDB serverless driver", "postgres.js"]}>
import 'dotenv/config';
import { Pool } from 'pg';
const pool = new Pool({
connectionString: process.env.DATABASE_URL,
ssl: {
require: true,
},
});
async function setup() {
const client = await pool.connect();
try {
console.log('Connection established');
// Drop the table if it already exists
await client.query('DROP TABLE IF EXISTS books;');
console.log('Finished dropping table (if it existed).');
// Create a new table
await client.query(`
CREATE TABLE books (
id SERIAL PRIMARY KEY,
title VARCHAR(255) NOT NULL,
author VARCHAR(255),
publication_year INT,
in_stock BOOLEAN DEFAULT TRUE
);
`);
console.log('Finished creating table.');
// Insert a single book record
await client.query(
'INSERT INTO books (title, author, publication_year, in_stock) VALUES ($1, $2, $3, $4);',
['The Catcher in the Rye', 'J.D. Salinger', 1951, true]
);
console.log('Inserted a single book.');
// Data to be inserted
const booksToInsert = [
{ title: 'The Hobbit', author: 'J.R.R. Tolkien', year: 1937, in_stock: true },
{ title: '1984', author: 'George Orwell', year: 1949, in_stock: true },
{ title: 'Dune', author: 'Frank Herbert', year: 1965, in_stock: false },
];
// Insert multiple books
for (const book of booksToInsert) {
await client.query(
'INSERT INTO books (title, author, publication_year, in_stock) VALUES ($1, $2, $3, $4);',
[book.title, book.author, book.year, book.in_stock]
);
}
console.log('Inserted 3 rows of data.');
} catch (err) {
console.error('Connection failed.', err.stack);
} finally {
client.release();
pool.end();
}
}
setup();import 'dotenv/config';
import { neon } from '@serenorg/serverless';
const sql = neon(process.env.DATABASE_URL);
async function setup() {
try {
console.log('Connection established');
// Drop the table if it already exists
await sql`DROP TABLE IF EXISTS books;`;
console.log('Finished dropping table (if it existed).');
// Create a new table
await sql`
CREATE TABLE books (
id SERIAL PRIMARY KEY,
title VARCHAR(255) NOT NULL,
author VARCHAR(255),
publication_year INT,
in_stock BOOLEAN DEFAULT TRUE
);
`;
console.log('Finished creating table.');
// Insert a single book record
await sql`
INSERT INTO books (title, author, publication_year, in_stock)
VALUES ('The Catcher in the Rye', 'J.D. Salinger', 1951, true);
`;
console.log('Inserted a single book.');
// Data to be inserted
const booksToInsert = [
{ title: 'The Hobbit', author: 'J.R.R. Tolkien', publication_year: 1937, in_stock: true },
{ title: '1984', author: 'George Orwell', publication_year: 1949, in_stock: true },
{ title: 'Dune', author: 'Frank Herbert', publication_year: 1965, in_stock: false },
];
// Insert multiple books
await sql`
INSERT INTO books (title, author, publication_year, in_stock)
VALUES (${booksToInsert[0].title}, ${booksToInsert[0].author}, ${booksToInsert[0].publication_year}, ${booksToInsert[0].in_stock}),
(${booksToInsert[1].title}, ${booksToInsert[1].author}, ${booksToInsert[1].publication_year}, ${booksToInsert[1].in_stock}),
(${booksToInsert[2].title}, ${booksToInsert[2].author}, ${booksToInsert[2].publication_year}, ${booksToInsert[2].in_stock});
`;
console.log('Inserted 3 rows of data.');
} catch (err) {
console.error('Connection failed.', err);
}
}
setup();import 'dotenv/config';
import postgres from 'postgres';
const sql = postgres(process.env.DATABASE_URL, {
ssl: 'require',
});
async function setup() {
try {
console.log('Connection established');
// Drop the table if it already exists
await sql`DROP TABLE IF EXISTS books;`;
console.log('Finished dropping table (if it existed).');
// Create a new table
await sql`
CREATE TABLE books (
id SERIAL PRIMARY KEY,
title VARCHAR(255) NOT NULL,
author VARCHAR(255),
publication_year INT,
in_stock BOOLEAN DEFAULT TRUE
);
`;
console.log('Finished creating table.');
// Insert a single book record
await sql`
INSERT INTO books (title, author, publication_year, in_stock)
VALUES ('The Catcher in the Rye', 'J.D. Salinger', 1951, true);
`;
console.log('Inserted a single book.');
// Data to be inserted
const booksToInsert = [
{ title: 'The Hobbit', author: 'J.R.R. Tolkien', publication_year: 1937, in_stock: true },
{ title: '1984', author: 'George Orwell', publication_year: 1949, in_stock: true },
{ title: 'Dune', author: 'Frank Herbert', publication_year: 1965, in_stock: false },
];
// Insert multiple books
await sql`
INSERT INTO books ${sql(booksToInsert, 'title', 'author', 'publication_year', 'in_stock')}
`;
console.log('Inserted 3 rows of data.');
} catch (err) {
console.error('Connection failed.', err);
} finally {
sql.end();
}
}
setup();The above code does the following:
Loads the connection string from the
.envfile.Connects to the SerenDB database.
Drops the
bookstable if it already exists to ensure a clean slate.Creates a table named
bookswith columns forid,title,author,publication_year, andin_stock.Inserts a single book record and then multiple book records.
Run the script using the command for your runtime:
node create_table.jsWhen the code runs successfully, it produces the following output:
Connection established
Finished dropping table (if it existed).
Finished creating table.
Inserted a single book.
Inserted 3 rows of data.Read data
In your project directory, create a file named read_data.js. This script connects to your SerenDB database and retrieves all rows from the books table.
<CodeTabs labels={[ "node-postgres (pg)","SerenDB serverless driver", "postgres.js"]}>
import 'dotenv/config';
import { Pool } from 'pg';
const pool = new Pool({
connectionString: process.env.DATABASE_URL,
ssl: {
require: true,
},
});
async function readData() {
const client = await pool.connect();
try {
console.log('Connection established');
// Fetch all rows from the books table
const { rows } = await client.query('SELECT * FROM books ORDER BY publication_year;');
console.log('\n--- Book Library ---');
rows.forEach((row) => {
console.log(
`ID: ${row.id}, Title: ${row.title}, Author: ${row.author}, Year: ${row.publication_year}, In Stock: ${row.in_stock}`
);
});
console.log('--------------------\n');
} catch (err) {
console.error('Connection failed.', err.stack);
} finally {
client.release();
pool.end();
}
}
readData();import 'dotenv/config';
import { neon } from '@serenorg/serverless';
const sql = neon(process.env.DATABASE_URL);
async function readData() {
try {
console.log('Connection established');
// Fetch all rows from the books table
const books = await sql`SELECT * FROM books ORDER BY publication_year;`;
console.log('\n--- Book Library ---');
books.forEach((book) => {
console.log(
`ID: ${book.id}, Title: ${book.title}, Author: ${book.author}, Year: ${book.publication_year}, In Stock: ${book.in_stock}`
);
});
console.log('--------------------\n');
} catch (err) {
console.error('Connection failed.', err);
}
}
readData();import 'dotenv/config';
import postgres from 'postgres';
const sql = postgres(process.env.DATABASE_URL, {
ssl: 'require',
});
async function readData() {
try {
console.log('Connection established');
// Fetch all rows from the books table
const books = await sql`SELECT * FROM books ORDER BY publication_year;`;
console.log('\n--- Book Library ---');
books.forEach((book) => {
console.log(
`ID: ${book.id}, Title: ${book.title}, Author: ${book.author}, Year: ${book.publication_year}, In Stock: ${book.in_stock}`
);
});
console.log('--------------------\n');
} catch (err) {
console.error('Connection failed.', err);
} finally {
sql.end();
}
}
readData();Run the script using the command for your runtime:
node read_data.jsWhen the code runs successfully, it produces the following output:
Connection established
--- Book Library ---
ID: 2, Title: The Hobbit, Author: J.R.R. Tolkien, Year: 1937, In Stock: true
ID: 3, Title: 1984, Author: George Orwell, Year: 1949, In Stock: true
ID: 1, Title: The Catcher in the Rye, Author: J.D. Salinger, Year: 1951, In Stock: true
ID: 4, Title: Dune, Author: Frank Herbert, Year: 1965, In Stock: false
--------------------Update data
In your project directory, create a file named update_data.js. This script connects to your SerenDB database and updates the stock status of the book 'Dune' to true.
<CodeTabs labels={["node-postgres (pg)","SerenDB serverless driver", "postgres.js"]}>
import 'dotenv/config';
import { Pool } from 'pg';
const pool = new Pool({
connectionString: process.env.DATABASE_URL,
ssl: {
require: true,
},
});
async function updateData() {
const client = await pool.connect();
try {
console.log('Connection established');
// Update a data row in the table
await client.query('UPDATE books SET in_stock = $1 WHERE title = $2;', [true, 'Dune']);
console.log("Updated stock status for 'Dune'.");
} catch (err) {
console.error('Connection failed.', err.stack);
} finally {
client.release();
pool.end();
}
}
updateData();import 'dotenv/config';
import { neon } from '@serenorg/serverless';
const sql = neon(process.env.DATABASE_URL);
async function updateData() {
try {
console.log('Connection established');
// Update a data row in the table
await sql`UPDATE books SET in_stock = ${true} WHERE title = ${'Dune'}`;
console.log("Updated stock status for 'Dune'.");
} catch (err) {
console.error('Connection failed.', err);
}
}
updateData();import 'dotenv/config';
import postgres from 'postgres';
const sql = postgres(process.env.DATABASE_URL, {
ssl: 'require',
});
async function updateData() {
try {
console.log('Connection established');
// Update a data row in the table
await sql`UPDATE books SET in_stock = ${true} WHERE title = ${'Dune'}`;
console.log("Updated stock status for 'Dune'.");
} catch (err) {
console.error('Connection failed.', err);
} finally {
sql.end();
}
}
updateData();Run the script using the command for your runtime:
node update_data.jsAfter running this script, you can run read_data.js again to verify the change.
node read_data.jsWhen the code runs successfully, it produces the following output:
Connection established
--- Book Library ---
ID: 2, Title: The Hobbit, Author: J.R.R. Tolkien, Year: 1937, In Stock: true
ID: 3, Title: 1984, Author: George Orwell, Year: 1949, In Stock: true
ID: 1, Title: The Catcher in the Rye, Author: J.D. Salinger, Year: 1951, In Stock: true
ID: 4, Title: Dune, Author: Frank Herbert, Year: 1965, In Stock: true
--------------------You can see that the stock status for 'Dune' has been updated to
true.
Delete data
In your project directory, create a file named delete_data.js. This script connects to your SerenDB database and deletes the book '1984' from the books table.
<CodeTabs labels={["node-postgres (pg)", "SerenDB serverless driver", "postgres.js"]}>
import 'dotenv/config';
import { Pool } from 'pg';
const pool = new Pool({
connectionString: process.env.DATABASE_URL,
ssl: {
require: true,
},
});
async function deleteData() {
const client = await pool.connect();
try {
console.log('Connection established');
// Delete a data row from the table
await client.query('DELETE FROM books WHERE title = $1;', ['1984']);
console.log("Deleted the book '1984' from the table.");
} catch (err) {
console.error('Connection failed.', err.stack);
} finally {
client.release();
pool.end();
}
}
deleteData();import 'dotenv/config';
import { neon } from '@serenorg/serverless';
const sql = neon(process.env.DATABASE_URL);
async function deleteData() {
try {
console.log('Connection established');
// Delete a data row from the table
await sql`DELETE FROM books WHERE title = ${'1984'}`;
console.log("Deleted the book '1984' from the table.");
} catch (err) {
console.error('Connection failed.', err);
}
}
deleteData();import 'dotenv/config';
import postgres from 'postgres';
const sql = postgres(process.env.DATABASE_URL, {
ssl: 'require',
});
async function deleteData() {
try {
console.log('Connection established');
// Delete a data row from the table
await sql`DELETE FROM books WHERE title = ${'1984'}`;
console.log("Deleted the book '1984' from the table.");
} catch (err) {
console.error('Connection failed.', err);
} finally {
sql.end();
}
}
deleteData();Run the script using the command for your runtime:
node delete_data.jsAfter running this script, you can run read_data.js again to verify that the row has been deleted.
node read_data.jsWhen the code runs successfully, it produces the following output:
Connection established
--- Book Library ---
ID: 2, Title: The Hobbit, Author: J.R.R. Tolkien, Year: 1937, In Stock: true
ID: 1, Title: The Catcher in the Rye, Author: J.D. Salinger, Year: 1951, In Stock: true
ID: 4, Title: Dune, Author: Frank Herbert, Year: 1965, In Stock: true
--------------------You can see that the book '1984' has been successfully deleted from the
bookstable.
Next steps: Using an ORM or framework
While this guide demonstrates raw SQL queries, for more advanced and maintainable data interactions, consider using an Object-Relational Mapper (ORM) or query builder. ORMs let you work with your data as objects and manage schema changes through migrations, keeping your database structure in sync with your application models.
Explore these guides to integrate popular data tools with SerenDB:
Using Bun or Deno
If you are using Bun or Deno, you can also connect to SerenDB databases using the SerenDB serverless driver or other Postgres clients. Follow these guides for more information:
Source code
You can find the source code for the applications described in this guide on GitHub.
Get started with node-postgres (pg)
Get started with the SerenDB Serverless Driver
Resources
Last updated