From Routes to Records: Connecting Express.js to MySQL or PostgreSQL

Imagine you're building a sleek web application with Express.js — the kind that handles routes like a pro, sends JSON like a champ, and throws errors with attitude. But there's a catch: all your data lives in a far-off land called MySQL or PostgreSQL, and Express is clueless about how to talk to it.
Let’s walk through the journey of connecting Express.js to one of these powerful relational databases. Whether you're saving user accounts, blog posts, or spaceship coordinates, it all starts with a bridge — a database driver.
Step 1: Preparing the Tools
You’ve already got your Express server up and running. Now it’s time to introduce the database. First, pick your companion:
-
For MySQL, use
mysql2
. -
For PostgreSQL, go with
pg
.
# MySQL
npm install mysql2
# PostgreSQL
npm install pg
Step 2: Setting Up the Connection
Every connection starts with trust — and connection credentials. Create a file like db.js
where you define the handshake between your server and your database.
For MySQL:
const mysql = require('mysql2');
const pool = mysql.createPool({
host: 'localhost',
user: 'your_db_user',
password: 'your_password',
database: 'your_database_name'
});
module.exports = pool.promise();
For PostgreSQL:
const { Pool } = require('pg');
const pool = new Pool({
host: 'localhost',
user: 'your_db_user',
password: 'your_password',
database: 'your_database_name',
port: 5432
});
module.exports = pool;
Now you’ve got a connection pool, a reusable pipeline your app can use to send and receive data without clogging up the works.
Step 3: Writing the Queries
Back in your Express routes, you can now use the pool
to interact with the database — to fetch, insert, update, or delete data.
Example: Fetching all users
const express = require('express');
const db = require('./db'); // our connection file
const app = express();
app.get('/users', async (req, res) => {
try {
const [rows] = await db.query('SELECT * FROM users');
res.json(rows);
} catch (err) {
console.error(err);
res.status(500).json({ error: 'Database error' });
}
});
Note: For PostgreSQL, the query call would be:
const result = await db.query('SELECT * FROM users');
res.json(result.rows);
Step 4: Handle It Gracefully
Things go wrong — maybe the database crashes, or someone tries to insert emoji into an integer field. Always wrap your queries in try/catch
blocks and return meaningful errors to keep your app robust.
Step 5: Scaling and Structuring
As your app grows, you'll want to:
-
Use ORMs like Sequelize (MySQL/Postgres) or Prisma for complex apps.
-
Add .env files to store your DB credentials securely.
-
Create data access layers to separate queries from your route logic.
Conclusion: The Power of Connection
With Express handling the routes and MySQL or PostgreSQL managing the data, you now have a full-stack relationship where the backend can serve data-rich responses. From handling user sign-ups to powering dashboards, this connection is the heartbeat of modern web development.
Your Express app is no longer just sending "Hello World" — it’s sending meaningful data pulled straight from your database, thanks to the connection you just built.