The REST API two lessons back stores products in a plain array — data that vanishes the instant the server restarts. A real application stores data in a database instead, so it survives restarts and can be shared safely across many requests at once.
Node.js has no built-in database support — connecting to one requires an npm package written for that specific database. A couple of common ones:
| Database | Common driver package |
|---|---|
| PostgreSQL | pg |
| MySQL | mysql2 |
| SQLite | better-sqlite3 |
The examples below use pg for PostgreSQL — the pattern (connect, then query with placeholders) looks nearly identical with the others, just with a different package name.
const { Pool } = require('pg')
const pool = new Pool({
host: process.env.DB_HOST,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
database: process.env.DB_NAME,
})Notice every value comes from process.env, not a hardcoded string — exactly the pattern from the earlier lesson on environment variables. A database password is precisely the kind of secret that should never appear directly in a source file.
Every query method returns a promise, so it fits naturally with async/await:
app.get('/products', async (req, res) => {
try {
const result = await pool.query('SELECT * FROM products')
res.json(result.rows)
} catch (err) {
console.error(err)
res.status(500).json({ error: 'Database query failed' })
}
})A value from a request must never be inserted directly into a query string:
// NEVER do this
const id = req.params.id
await pool.query(`SELECT * FROM products WHERE id = ${id}`)A visitor who sends a crafted id value instead of a number can use this to run arbitrary SQL against the database — a SQL injection attack. Use a placeholder instead, and pass the value as a separate parameter:
const id = req.params.id
const result = await pool.query('SELECT * FROM products WHERE id = $1', [id])The driver handles escaping the value safely — this single habit is the difference between a normal query and an exploitable one.
Where the SQL syntax itself is taught
This lesson only covers connecting Node to a database that already exists. Writing the SQL itself — SELECT, WHERE, joins, and everything else in a query — is covered in full in this site's SQL course.