Building a Multi-Tenant Application in Node.js with PostgreSQL

shourya saxena
3 min readJul 24, 2024

--

Multi tenant archietecture

In the world of SaaS (Software as a Service), multi-tenancy is a key concept. A multi-tenant application serves multiple customers (tenants) from a single instance of the software while ensuring data isolation and security. In this article, we’ll explore how to build a multi-tenant application using Node.js and PostgreSQL with Sequelize.

Logic/Concept:

  1. There will be multiple different database which is to be added.
  2. Code for node and Schema will be same for all other databases.
  3. We will figure out tenant ie… which database to be used, so for that we will find ‘host’ which comes in header at the time of request.
  4. At last we will make a function which will keep switching our database according to the request comes.

Step 1: Setting Up the Project

First, set up a new Node.js project.

mkdir multi-tenant-app
cd multi-tenant-app
npm init -y
npm install express sequelize pg pg-hstore

Step 2: Configuring Express and Sequelize

Create a basic Express server and configure Sequelize to connect to PostgreSQL. (server.js root file)

const express = require('express');
const getDatabaseInstance = require('./db');
const defineUserModel = require('./models');

const app = express();
const port = 3000;

app.use(express.json());


// Route to create a new user
app.post('/users', async (req, res) => {
console.log("consoled it from middleware tenantId",req.tenantId)
try {
let dbChoice = req.headers.host
console.log("thi s is db choice =======???????????????? Boom guys",dbChoice)
let tenantIdD;

if (dbChoice === "localhost:3000") { //just define your host name here
tenantIdD = "tenant1";
} else if (dbChoice === "two") {
tenantIdD = "tenant2";
} else {
return res.status(400).json({ msg: "Invalid database Choice", status: false });
}
// const sequelize = getDatabaseInstance(req.tenantId);
const sequelize = getDatabaseInstance(tenantIdD);

// console.log("this is controller sequilize-------------->>>>>>>>>>>>",sequelize)
const User = defineUserModel(sequelize);
// await sequelize.sync(); // Ensure table creation for the tenant schema
const user = await User.create(req.body);
if (!user) {
return res.json({ msg: `user not created`, status: false })
} else {
res.status(201).json(user);
}


} catch (error) {
console.error("Error=========>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>",error);
res.status(500).send('Internal Server Error');
}
});

// Start the server
app.listen(port, () => {
console.log(`Server running on http://localhost:${port}`);
});

Step 3: Setting Up the Tenant Model

Define a Tenant model in Sequelize. (models.js root file)

const { DataTypes } = require('sequelize');

// Function to define the User model for a given Sequelize instance
const defineUserModel = (sequelize) => {
return sequelize.define('user', {
id: {
type: DataTypes.INTEGER,
autoIncrement: true,
primaryKey: true,
},
name: {
type: DataTypes.STRING,
allowNull: false,
},
email: {
type: DataTypes.STRING,
allowNull: false,
unique: true,
},
});
};

module.exports = defineUserModel;

Step 4: Creating Tenant for Identification

Create the tenant based on the request and set the database connection accordingly. (db.js root file)

const { Sequelize } = require('sequelize');

// Database connection configurations
const databases = {
tenant1: new Sequelize('logisticLocal', 'postgres', '12345', {
host: 'localhost',
port: '5433',
dialect: 'postgres',
logging: false,
}),
tenant2: new Sequelize('test', 'postgres', '12345', {
host: 'localhost',
port: '5433',
dialect: 'postgres',
logging: false,
}),
};


// Function to get a Sequelize instance for a tenant
const getDatabaseInstance = (tenantId) => {
return databases[tenantId];
};

module.exports = getDatabaseInstance;

So here i have added multiple database connection and made a function ‘getDatabaseInstance’ which will help to switch database connection.

Finally run cammand to start the node server

node server.js

Conclusion

In this article, we’ve created a basic multi-tenant application in Node.js with PostgreSQL. We used Sequelize for ORM and Express for handling HTTP requests. By implementing tenant switching function to dynamically switch database connections, we’ve ensured data isolation between tenants. This setup provides a scalable foundation for a multi-tenant SaaS application.

--

--

shourya saxena
shourya saxena

Written by shourya saxena

"Driven by happiness, I embrace the journey of acquiring knowledge. With knowledge as my guide, I strive towards success."

No responses yet