ALogRocket
BLOG
CRUD REST API with Node.js, Express, and
PostgreSQL
May 23, 2022 - 12 min read
Editor’s note: This post was updated on 06 June 2022 to reflect updates to the pgAdmin
client.
For a modern web developer, knowing how to work with APIs to facilitate
communication between software systems is paramount. In this tutorial, we'll
Jearn how to create a CRUD RESTful API in a Node.js environment that runs on an.
Express server and uses a PostgreSQL database. We'll also walk through
connecting an Express server with PostgreSQL using node-postgres.
Our API will be able to handle the HTTP request methods that correspond to the
PostgreSQL database from which the API gets its data. You’ll also learn how to
install PostgreSQL and work with it through the command-line interface.
Our goal is to allow CRUD operations, cet , post , pur ,and péLeTe , on the API,
which will run the corresponding database commands. To do so, we'll set up a
route for each endpoint and a function for each query.
‘We'll cover the following in detail:
+ What is a RESTful API?
+ What isa CRUD API?
* What is Express?
+ What is PostgreSQL?
+ What is node-postgres?+ Creating a PostgreSQL database
+ PostgreSQL command prompt
+ Creating a role in Postgres
+ Creating a database in Postgres
+ Creating a table in Postgres
+ Setting up an Express server
+ Connecting to a Postgres database from Nodes
+ Creating routes for CRUD operations
+ Exporting CRUD functions in a REST API
+ Setting up CRUD functions in a REST API
To follow along with this tutorial, you‘ll need:
+ Familiarity with the JavaScript syntax and fundamentals
+ Basic knowledge of working with the command line
+ Nodes and npm installed
‘The complete code for the tutorial is available on this GitHub repo. Let’s get
started!
What is a RESTful API?
Representational State Transfer (REST) defines a set of standards for web
services. An API is an interface that software programs use to communicate with
each other. Therefore, a RESTful API is an API that conforms to the REST
architectural style and constraints. REST systems are stateless, scalable,
cacheable, and have a uniform interface.
What is a CRUD API?
When building an API, you want your model to provide four basic functionalities.
It should be able to create, read, update, and delete resources. This set of essential
operations is commonly referred to as CRUD.RESTful APIs most commonly utilize HTTP requests. Four of the most common
HTTP methods in a REST environment are cet, post , pur ,and veLere , which
are the methods by which a developer can create a CRUD system.
+ create :Usethe HTTP post method to create a resource in a REST
environment
+ Read : Use the cer method to read a resource, retrieving data without
altering it
+ Update : Use the put method to update a resource
* velete :Use the pe.ete method to remove a resource from the system
What is Express?
According to the official Express documentation, Express is a fast, un-
opinionated, minimalist web framework for Nodes. Express is one of the most
popular frameworks for Node,js. In fact, the E in MERN, MEVN, and MEAN stack
stands for Express.
Although Express is minimalist, it is also very flexible, leading to the
development of various Express middlewares that you can use to address almost
any task or problem imaginable.
What is PostgreSQL?
PostgreSQL, commonly referred to as Postgres, is a free, open source relational
database management system. You might be familiar with a few other similar
database systems, like MySQL, Microsoft SQL Server, or MariaDB, which compete
with PostgreSQL.
PostgreSQL is a robust relational database that has been around since 1997 and is
available on all major operating systems, Linux, Windows, and macOS. Since
PostgreSQL is known for stability, extensibility, and standards compliance, it’s a
popular choice for developers and companies.It’s also possible to create a Node.js RESTful CRUD API using Sequelize. Sequelize
is a promise-based Node.js ORM for for Postgres, MySQL, MariaDB, SQLite, and
Microsoft SQL Server.
For more on how to use Sequelize in a Node.js REST API, check out the video
tutorial below:
Building an API in Node.js with Express and S...
What is node-postgres?
node-postgres, or pg, is anonblocking PostgreSQL. client for Nodes. Essentially,
node-postgres is a collection of Node.js modules for interfacing with a
PostgreSQL database.
Among the many features node-postgres supports include callbacks, promises,
async/await, connection pooling, prepared statements, cursors, rich type
parsing, and C/C++ bindings.
Creating a PostgreSQL databaseWe'll begin this tutorial by installing PostgreSQL, creating a new user, creating a
database, and initializing a table with a schema and some data.
Installation
If you're using Windows, download a Windows installer of PostgreSQL.
If you're using a Mac, this tutorial assumes you have Homebrew installed on your
computer as a package manager for installing new programs. If you don’t, simply
click on the link and follow the instructions.
Open up the Terminal and install postgresql with brew :
brew install postgresql
You may see instructions on the web reading brew install postgres instead of
postgresql ; both options will install PostgreSQL on your computer.
After the installation is complete, we'll want to get postgresql up and running,
which we can do with services start :
brew services start postgresql
==> Successfully started postgresql’ (label: homebrew.mxcl. postgresql)
If at any point you want to stop the postgresql service, you can run brew services
stop postgresql .
With PostgreSQL installed, next, we'll connect to the postgres command line
where we can run SQL commands.
PostgreSQL command promptpsql is the PostgreSQL interactive terminal. Running psqi will connect you toa
PostgreSQL host. Running psql --help will give you more information about the
available options for connecting with psqi :
-host=HosTName : The database server host or socket directory; the
default is local socket
+ -p: --port=porr : The database server port; the default is s432
* -U: --username=USERNAME : The database username; the default is
your_username
+ “ws --no-password : Never prompt for password
eos
-password : Force password prompt, which should happen
automatically
We'll connect to the default postgres database with the default login information
and no option flags:
psql postgres
You'll see that we’ve entered into a new connection. We’ re now inside psql in
the postgres database. The prompt ends witha # to denote that we're logged in
as the superuser, or root:
postgres=#
Commands within psqi start witha backslash \ . ‘To test our first command, we
can check what database, user, and port we’ve connected to using the \conninfo
command.
postgres-# \conninfo
You are connected to database “postgres” as user "your_username" via socket in
“/emp" at port "5432".‘The reference table below includes a few common commands that we’ ll use
throughout this tutori
+ \q:Exit psqi connection
+ \c : Connect to a new database
+ \gt : List all tables
+ \du : List all roles
+ \list : List databases
Let’s create a new database and user so we're not using the default accounts,
which have superuser privileges.
Creating a role in Postgres
First, we'll create a role called me and give it a password of password .Arole can
function as a user or a group. In this case, we'll use it as a user:
postgres=# CREATE ROLE me WITH LOGIN PASSWORD ‘password’;
We want me tobe able to create a database:
postgres=# ALTER ROLE me CREATEDB;
Youcanrun \du to list all roles and users:
me | Create DB 1a
postgres | Superuser, Create role, Create 0B | (}
Now, we want to create a database from the me user. Exit from the default
session with \q for quit:postgres=# \q
We're back in our computer’s default terminal connection. Now, we’ll connect
postgres with me :
psql -d postgres -U me
Instead of postgres-# , our prompt now shows postgres-> , meaning we're no
longer logged in as a superuser.
Creating a database in Postgres
We can create a database with the SQL command as follows:
postgres=> CREATE DATABASE api;
Use the \list command to see the available databases:
Name | Owner =| Encoding | Collate | Ctype =|
api | me | uTF8 | en_us.UTF-8 | en_us.UTF-8 |
Let’s connect to the new api database with me using the \c connect command:
postgres=> \c api
You are now connected to database "api" as user "me".
api=>
Our prompt now shows that we’re connected to api .
Creating a table in PostgresFinally, inthe psq1 command prompt, we'll create a table called users with
three fields, two varcuar types, and an auto-incrementing priMary KEY I
api=>
CREATE TABLE users (
ID SERIAL PRIMARY KEY,
ame VARCHAR(3@),
email VARCHAR(30)
v3
Make sure not to use the backtick * character when creating and working with
tables in PostgreSQL. While backticks are allowed in MySQL, they’re not valid in
PostgreSQL. Also ensure that you do not have a trailing comma in the create
TABLE command.
Let’s add some data to work with by adding two entries to users :
INSERT INTO users (name, email)
VALUES (‘Jerry', ‘
[email protected]'), (‘George’, ‘
[email protected]');
Let’s make sure that the information above was correctly added by getting all
entries in users :
api=> SELECT * FROM users;
id | name | email
1 | Jerry |
[email protected]
2 | George |
[email protected]
Now, we have a user, database, table, and some data. We can begin building our
Node,js RESTful API to connect to this data, stored in a PostgreSQL database.At this point, we’re finished with all of our PostgreSQL tasks, and we can begin
setting up our Nodes app and Express server.
Setting up an Express server
To set up a Nodes app and Express server, first create a directory for the project
to live in:
mkdir node-api-postgres
cd node-api-postgres
Youcaneither run npm init -y tocreatea package. json file, or copy the code
below intoa package. json file:
"name": "node-api-postgres”,
"version": "1.0.0",
“description”: “RESTful API with Node.js, Express, and PostgreSQL",
main": "index.js",
"license": "MIT"
We'll want to install Express for the server and node-postgres to connect to
PostgreSQL:
npm i express pg
Now, we have our dependencies loaded into node_modules and package.4son .
Create an index. js file, which we'll use as the entry point for our server. At the
top, we'll require the express module, the built-in body-parser middleware, and
we'll set our app and port variables:const express = require(‘express')
const bodyParser = require('body-parser’)
const app = express()
const port = 3000
app.use(bodyParser.json())
app.use(
bodyParser.urlencoded ({
extended: true,
»
‘We'll tell a route to look fora cet request on the root / URL and return some
JSON:
app.get("/', (request, response) => {
response. json({ info: 'Node.js, Express, and Postgres API' })
»
Now, set the app to listen on the port you set:
app.listen(port, () => {
console. log(*App running on port ${port}.”)
»
From the command line, we can start the server by hitting index.js :
node index.js
App running on port 3000.
Goto http://localhost:3¢e@ in the URL bar of your browser, and you'll see the
JSON we set earlier:jode.js, Express, and Postgres API"
The Express server is running now, but it’s only sending some static JSON data
that we created. The next step is to connect to PostgreSQL from Node,js to be able
to make dynamic queries.
Connecting to a Postgres database using a
Client
Apopular client for accessing Postgres databases is the pgAdmin client. The
pgAdmin application is available for various platforms. If you want to have a
graphical user interface for your Postgres databases, you can go to the download
page and download the necessary package.
Creating and querying your database using pgAdmin is simple. You need to click
on the Object option available on the top menu, select Create, and choose
Database to create a new connection. All the databases are available on the side
menu. You can query or run SQL queries efficiently by selecting the proper
database:
Connecting to a Postgres database from
Node.js
We'll use the node-postgres module to create a pool of connections. Therefore,
we don’t have to open and close a client each time we make a query.
A popular option for production pooling would be to use pgBouncer , a lightweight
connection pooler for PostgreSQL.Create a file called queries.js and set up the configuration of your PostgreSQL
connection:
const Pool = require('pg').Pool.
const pool = new Pool({
user: ‘me’,
host: ‘localhost',
database: ‘api’,
password: ‘password’,
port: 5432,
»
Ina production environment, you would want to put your configuration details in
a separate file with restrictive permissions so that it is not accessible from
version control. But, for the simplicity of this tutorial, we'll keep it in the same
file as the queries.
The aim of this tutorial is to allow CRUD operations, cet , post , pur ,and
DELETE on the API, which will run the corresponding database commands. To do
so, we'll set up a route for each endpoint and a function corresponding to each
query.
Creating routes for CRUD operations
We'll create six functions for six routes, as shown below. First, create all the
functions for each route. Then, export the functions so they’re accessible:
© GET: / | displayHome()
* GET: /users | getUsers()
* GET: /users/:id | getUserBytd()
* Post: /users | createUser()
© PUT: /users/:id | updateUser()
+ DELETE : /users/:id | deleteuser()In index.js ,we made an app.get() for the root endpoint with a function in it.
Now, in queries. js , we'll create endpoints that will display all users, display a
single user, create a new user, update an existing user, and delete a user.
GET all users
Our first endpoint will bea cer request. We can put the raw SQl. that will touch
the api database inside the pool.query() .We'll setect all users and order by
ID.
const getUsers = (request, response) => {
pool.query('SELECT * FROM users ORDER BY id ASC’, (error, results) => {
if (error) {
‘throw error
?
response. status (200). json(results. rows)
»
GET a single user by ID
For our /users/:id request, we'll get the custom id parameter by the URL and
use a WHERE clause to display the result.
In the SQL query, we're looking for id-$1 . Inthis instance, $1 is a numbered
placeholder that PostgreSQL uses natively instead of the > placeholder that you
may recognize from other variations of SQconst getUserById = (request, response) => {
const id = parselnt(request.params. id)
pool.query('SELECT * FROM users WHERE id = $1°, [id], (error, results) => (
if (error) {
‘throw error
+
response. status(200). json(results. rows)
»
POST anew user
The API will take a cer and post request to the /users endpoint. Inthe Post
request, we'll add a new user. In this function, we’re extracting the sane and
enail properties from the request body and inserting the values with insert :
const createUser =
request, response) => {
const { name, email } = request. body
pool.query( "INSERT INTO users (name, email) VALUES ($1, $2) RETURNING *",
[name, email], (error, results) => {
if (error) {
‘throw error
+
response. status (201).send("User added with ID: ${results.rows[@].id}")
»
PUT updated data in an existing user‘The /users/:id endpoint will also take two HTTP requests, the cet we created
for getusertyid anda pur to modify an existing user. For this query, we'll
combine what we learned in cet and post touse the urvate clause.
It’s worth noting that put is idempotent, meaning the exact same call can be
made over and over and will produce the same result. pur is different than post ,
in which the exact same call repeated will continuously make new users with the
same data:
const updateUser = (request, response) => {
const id = parsetnt(request.params. id)
const { name, enail } = request.body
pool. query(
“UPDATE users SET name = $1, email = $2 WHERE id = $3",
[nane, email, id],
(error, results) => (
if (error) {
throw error
+
response. status(200).send(*User modified with 1D: ${id}")
DELETE auser
Finally, we'll use the vetete clause on /users/:id to delete a specific user by ID.
This call is very similar to our getusersyr4() function:const deleteUser = (request, response) => {
const id = parselnt(request.params. id)
pool.query( DELETE FROM users WHERE id = $1", [id], (error, results) => {
if (error) (
‘throw error
}
response. status(200).send(*User deleted with ID: ${id}")
»
Exporting CRUD functions in a REST API
To access these functions from index. js , we’ll need to export them. We can do so
With module.exports , creating an object of functions. Since we’re using the ES6
syntax, we can write getUsers instead of getUsers:getUsers and soon:
module.exports = {
getusers,
getUserById,
createUser,
updateuser,
deleteUser,
Our complete queries. is file is beloconst Pool = require(‘pg').Pool
const pool = new Pool({
user: ‘me’,
host: ‘localhost’,
database: ‘api’,
Password: ‘password",
port: 5432,
»
const getUsers = (request, response) => {
pool.query('SELECT * FROM users ORDER BY id ASC', (error, results) => {
if (error) {
‘throw error
+
response. status (200). json(results. rows)
»
const getUserById = (request, response) => {
const id = parseInt(request.parans.id)
Setting up CRUD functions in a REST API
Now that we have all of our queries, we need to pull them into the index. js file
and make endpoint routes for all the query functions we created.
‘To get all the exported functions from queries. js , we'll require the file and
assign it to a variable:
const db = require(’./queries')
Now, for each endpoint, we'll set the HTTP request method, the endpoint URL
path, and the relevant function:app.get("/users', db.getUsers)
app.get('/users/:id", db. getUserById)
app.post(‘/users', db.createUser)
app.put('/users/:id’, db.updateUser)
app.delete('/users/:id', db.deleteUser)
Below is our complete index.js file, the entry point of the API server:
const express = require(‘express’)
const bodyParser
= require('body-parser')
const app = express()
const db = require(’./queries')
const port = 3000
app.use(bodyParser.json())
app.use(
bodyParser.urlencoded({
extended: true,
»
app.get('/', (request, response) => (
response. json({ info: ‘Node.js, Express, and Postgres API' })
»
app.get("/users’, db.getUsers)
app.get('/users/:id", db. getUserById)
With just these two files, we have a server, database, and our API all set up. You
can start up the server by hitting index.js again:
node index. js
‘App running on port 3000.Now, if you go to http: //localhost:3000/users OF http://localhost:3000/users/1 ,
you’ ll see the JSON response of the two ceT requests.
To test our post, put ,and vELeTe requests, we can use a tool like Postman or a
VS Code extension like Thunder Client to send the HTTP requests. You can also
use curl, acommand-line tool that is already available on your terminal.
Using a Postman or Thunder Client tool makes it simple to query endpoints with
different HTTP methods. Simply enter your URL, choose the specific HTTP
method, insert JSON value if the endpoint is a PUT or POST route, and hit send:
‘The example above shows sending a post request to the specified route. The
post option suggests that itis a post request. The URL beside the method is the
API endpoint, and the JSON content is the data to be sent to the endpoint. You can
hit the different routes similarly.
Conclusion
You should now have a functioning API server that runs on Nodes and is hooked
up to an active PostgreSQL database. In this tutorial, we learned how to install
and set up PostgreSQl. in the command line, create users, databases, and tables,
and run SQL commands. We also learned how to create an Express server that can
handle multiple HT'TP methods and use the pg module to connect to PostgreSQL
from Nodejs.
With this knowledge, you should be able to build on this API and utilize it for your
own personal or professional development projects.
Tania Rascia
ind me online at tania.dev,finode postgresql
Stop guessing why bugs
happen with LogRocket
Get started for
free
77 Replies to “CRUD REST API with Node,js, Express, and PostgreSQL”
Phaiza Says: Reply
August 19, 2020 at 10:08 pm
thank you!
Thankful Reader Says: Reply
September 24, 2020 at 12:28 pm
This is a wonderful article! Thank you for this!
Roger Says: Reply)
October 2, 2020 at 6:45 amthis is finally what i’ve been looking for. great start that can be easily expanded
by the readers needs,
Jodoinscott Says: Reply,
October 6, 2020 at 4:19 pm
Ineeded to use
psql -d postgres -h localhost -U me
to log in, otherwise I got
psql: error: could not connect to server: FA'LAL: Peer authentication failed for
user “me”
Jodoinscott Says: Reply
October 6, 2020 at 4:41 pm
This is great! Exactly what I was looking for. Note there is an error in the POST
code snippet. ‘results’ should be ‘result’.
Jodoinscott Says: Reply
October 6, 2020 at 4:50 pm
Good point. Still true.
Jodoinscott Says: Reply
October 6, 2020 at 4:51 pm
Great response. Thanks for the help!
Yared Solomon Says: Reply
November 5, 2020 at 11:02 pmThank you so much. this is all what i want
Wetbadger Says: Reply
January 29, 2021 at 11:51 am
1’m confused. Everything works except why would there be a json response on
localhost:3000/users ? I don’t see anything there. Am I supposed have a
users.html?
Luis Montalvo Says: Reply
February 3, 2021 at 10:39 pm
Hi Tania,
‘Thanks very much for your very clear and concise example. I followed it closely.
‘There was only 1 problem I ran into, which is when creating a user, I could not get
back the inserted 1D.
J looked this up, and for PosrgreSQL, there is a different way in which the id i
returned after an insert, as follows:
const createUser = (request, response
const { username, email } = request.body;
{
pool.query(
“INSERT INTO users (username, email) VALUES ($1,$2) RETURNING id”,
(username, email],
(error, results) => {
if (error) {
throw error;
3
response.status(201).send(‘User added with ID:$f{results.rows[0].id}*);
yi
3
‘The key is in getting the SQL statement correctly, with the “RETURNING id” bit
at the end.
Hopefully this will help others if they find the same problem.Best,
Luis
Sentinel1909 Says: Reply
July 18, 2021 at 11:27 pm
OMG! Thankyou so much, was on the verge of tearing my hair out here...
e
Dehangusc Says: Reply
February 8, 2021 at 4:54 pm
yep! it took me awhile to figure it out. thanks
Jord Says: Reply
February 20, 2021 at 10:59 am
Nice at first I thought it was the apostrophe formatting, I actually had the
RETURNING id part but couldnt get the results.rows piece - thank you!
Matt Says: Reply
March 5, 2021 at 5:42 pm
‘Sweet tutorial! thanks for the work, it is very easy to follow and works like a
charm @
Alex Says: Reply,
March 10, 2021 at 4:58 pm
Iseem to be getting this error when I run node index,js at the end: error:
password authentication failed for user “testuser”
Is there a fix for this?‘Adnan Lubis Says: Reply
March 29, 2021 at 5:58 am
Thanks
Abhishek Amrut Kamble Says Replys
March 31, 2024 at 10:29 pm
thank you so much
John Says: Reply
June 12, 2021 at 11:25 pm
I’ve copied the 2 files completely and when I try and localhost:3000/users it just
spins forever. Any way to trace the error?
‘Simmons Says: Reply
December 19, 2021 at 4:20 pm
I’ve failed to INSERT entries via Srequest.body, I had to use Srequest.query and
T’m stunned nobody else had this issue
‘The results.rows{0].id thing isn’t working for me either @
Pepper Says: Reply
June 16, 2022 at 12:11 am
Thank you! I had the issue with $request.body as well and changing it to
Srequest.query fixed it.
Not sure about results.rows[0] thing though, that one works on my
machine.
Vitaliy Says:December 30, 2021 at 8:55 am Reply
Hil I find the text hetween the headlines “Installation” and “PostgreSQL.
command prompt” to be misleading. I’m using Windows and it is unlear to me
which of those passages are releveant to my OS and whether I have to run any
brew-based or commands or similar ones in npm after downloading the
Windows installer (and running it, obviously, though not mentioned) and passin
on to the PostgreSQL command prompt section, Clarifications would be
appreciated.
Simo Says’ Reply
March 17, 2022 at 6:14 am
Very nice, Thank you so much ®
lan Says: Reply
June 10, 2022 at 8:03 pm
How doI “hit index.js””? How do I run this?
Parmeshwar Rathod Says: Reply
June 25, 2022 at 5:40 am
thanks alot man
such great content
Robert Werner Says Reply
June 30, 2022 at 12:05 pm
Tania, I ama very accomplished React & C# & Python software engineer but am
working on my own project now. I was all set to have a Python back-end, like is at
my work but then learned about Express,js. Thank you SO MUCH for your
excellent, most comprehensive article. It served as the template for building the
back-end of my ever evolving application.By the way, I’ve built both front-end and back-end with TypeScript so upgraded
your Javascript code to TypeScript. Feel free to contact me and I will gladly share
my code with you in case you want to update this article or follow-up with
another,
12
Leave a Reply
Enter your comment here.