Express and database instance practice

Without planning database connection instance in architecture, you'll end up in situation where you have copied connection code everywhere. In worst situation even database credentials are in multiple places.

What should we focus on?

Let's make couple important values:

  • Don't repeat yourself (DRY)
  • Making a new database connection is slow
  • Easy maintenance / Keep it simple, stupid (KISS)
  • Less code (Important in JavaScript)

Base situation

We have Node Express app with architecture where models and controllers are separated.

// app.js
const express = require('express');
const room = require('./controllers/room');
const user = require('./controllers/user');

const app = express();

app.use('/room', room);
app.use('/user', user);

app.get('/', (req, res) => {
  res.send('Hello World!')
})

app.listen(3000, () => {
  console.log('Example app listening on port 3000!')
})

Models are included in controllers which handle routes for specific model.

In bad situation we would have repeated database connection code with requirements into every model with credentials.

Good practice

Everything goes trough main file app.js. We shoudld create database instance there and call instance in another places. So external module is needed. node-postrgres / pg module is used in examples.

// db.js
const { Pool } = require('pg');

const state = {
  pool: null,
}

module.exports.connect = (cb) => {
  state.pool = new Pool({
    hostname: '127.0.0.1',
    port: '5432',
    database: 'superdb',
    user: 'username',
    password: password,
  });
  cb();
}

module.exports.get = () => {
  return state.pool;
}

And examples below shows how it's used. We create database connection instance only once in app.js. After connection we start express port listening.

// app.js
...
const db = require('db);

...

// Connect database
db.connect(() => {
  // Connect server
  app.listen(3000, () => {
    console.log('Example app listening on port 3000!')
  })
);

In models we call the same instance object with .get() method.

// models/user.js
const db = require('db);

module.exports.get = (id) => {
  db.get().query('SELECT FROM accouts WHERE id = ?', [id], (err, result) => {
    if (err) throw err;
    return result;
  });
}

That's it. Database module (db.js) could also include development specific methods like building database if not done already. This is just a base. Many ways to improve.