How I built a Multi-tenant SaaS product in Node.js

A few months ago, I had to build an URL-based Multi-tenant SaaS product using Node.js. I had no idea what it is. So I googled “What is a multi-tenant architecture”, “How to build a multi-tenant architecture in Node.js”, and so on. Unfortunately, I coul…


This content originally appeared on DEV Community and was authored by Muhamed Sufail

A few months ago, I had to build an URL-based Multi-tenant SaaS product using Node.js. I had no idea what it is. So I googled "What is a multi-tenant architecture", "How to build a multi-tenant architecture in Node.js", and so on. Unfortunately, I couldn't find a lot of helpful content but finally, I found out about Knex (pronounced /kəˈnɛks/), which is a powerful SQL query builder. I want to take this as an opportunity to share something which I hope some people will find relevant and useful.

Multitenant Architecture is a type of software architecture where a single instance of the software can serve multiple user groups. These user groups are called tenants.

Single-And-Multitenancy

In a Single-tenant,

  • Separate Applications.
  • Separate Databases

In Multi-tenant,

  • Same Application
  • Separate Databases

Types of Multitenancy

There are two main multi-tenancy architectural models when it comes to separating data of tenants

  1. Single database for each tenant
  2. Single database with different tables for each tenant

Types-Of-Multitenancy

Knex.js

According to its official website, Knex.js is a "batteries included" SQL query builder for PostgreSQL, CockroachDB, MSSQL, MySQL, MariaDB, SQLite3, Better-SQLite3, Oracle, and Amazon Redshift designed to be flexible, portable, and fun to use.

Now let's get our hands dirty by building a multi-tenant architecture in Node.js. In the following example, we'll be using different tables within a single database for each tenant's approach.

Pre-requisites

  • Basics of Node.js with express library

Setup

Create a new folder and initialize a node.js project by creating a package.json file by entering the following command in CLI.

$ npm init -y

Install express, knex and pg packages. (pg is a PostgreSQL client for Node.js)

$ npm install express knex pg

Create index.js file in the root folder. This will be the entry point to the application.

Database Schema

Image description

Code Explanation

Note: For ease of understanding, I'm not using best code practices

1. Knex Configuration

Create a db.js file. This is where we'll configure Knex to make a connection to the database.

db.js
Import knex module using require() function.

const knex = require("knex");

Call the top-level function knex() exported by the Knex module which takes a configuration object, accepting a few parameters.

const db = knex({
  client: "postgresql",
  connection: {
    database: "mutitenancy-node",
    user: "postgres",
    password: "postgres",
  },
});

Export the db variable so that it can be used elsewhere in the application.

module.exports = db;

2. Setting Up a Basic Server

index.js

Import express in your application using require() function.

const express = require("express");

Call the top-level function express() exported by the express module.

const app = express()

Import the default export function in db.js file

const knex = require("./db.js");

Mount the express.json() middleware function using the use() method of the app object to parse JSON in the request body.

app.use(express.json());

Listen to the server by the listen() method of the app object.

app.listen(4000, () => {
  console.log("Server listening to Port 4000");
});

3. Creating a Tenant

Create a tenants table through migration or manually with the following fields.

  • id - uuid
  • name - character varying
  • subdomain - character varying
  • admin_email - character varying

Whenever a new tenant register into our SaaS application, insert their details into the tenants table and also create a users table for the users of the tenant prefixed by the subdomain name (tenantname_users).

Create a POST request route /create-tenant using
the post() method of the app object.

app.post('/create-tenant', async (req, res) => {


})

Inside the body of the call back function, obtain the value of name, subdomain, and adminEmail property from the body of the request.

const { name, subdomain, adminEmail } = req.body;

Insert the details of the tenant into the tenants table

await knex("tenants").insert({
      name,
      subdomain,
      admin_email: adminEmail,
    });

Now, create a table for the users of the tenant

await knex.schema.createTable(`${subdomain}_users`, (table) => {
    table.uuid("id").defaultTo(knex.raw("uuid_generate_v4()"));
    table.string("first_name");
    table.string("last_name");
    table.string("email").unique();
  });

Send a response back to the client using the send() method.

  res.send("Tenant Created");

4. Inserting into users table

Create a POST request route /create-user using
the post() method of the app object.

app.post('/create-user', async (req, res) => {


})

Obtain the subdomain of the requesting client using subdomains array of req object.

const subdomain = req.subdomains[0];

Note: To have a dynamic URL for each tenant, you might need to use Nginx with your frontend application.

Since we are using localhost, obtain the subdomain and user details from the request body.

const { firstName, lastName, email, subdomain } = req.body;

Insert the details of the user into users table of that particular tenant

await knex(`${subdomain}_users`).insert({
    first_name: firstName,
    last_name: lastName,
    email,
  });

Send a response back to the client using the send() method.

res.send("User Created !!");

Wrap Up

Since we're using a single database, requests from multiple tenants can lead to a noisy-neighbor effect, which causes network performance issues.

Complete Code
Github

Credits


This content originally appeared on DEV Community and was authored by Muhamed Sufail


Print Share Comment Cite Upload Translate Updates
APA

Muhamed Sufail | Sciencx (2022-01-31T01:24:37+00:00) How I built a Multi-tenant SaaS product in Node.js. Retrieved from https://www.scien.cx/2022/01/31/how-i-built-a-multi-tenant-saas-product-in-node-js/

MLA
" » How I built a Multi-tenant SaaS product in Node.js." Muhamed Sufail | Sciencx - Monday January 31, 2022, https://www.scien.cx/2022/01/31/how-i-built-a-multi-tenant-saas-product-in-node-js/
HARVARD
Muhamed Sufail | Sciencx Monday January 31, 2022 » How I built a Multi-tenant SaaS product in Node.js., viewed ,<https://www.scien.cx/2022/01/31/how-i-built-a-multi-tenant-saas-product-in-node-js/>
VANCOUVER
Muhamed Sufail | Sciencx - » How I built a Multi-tenant SaaS product in Node.js. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2022/01/31/how-i-built-a-multi-tenant-saas-product-in-node-js/
CHICAGO
" » How I built a Multi-tenant SaaS product in Node.js." Muhamed Sufail | Sciencx - Accessed . https://www.scien.cx/2022/01/31/how-i-built-a-multi-tenant-saas-product-in-node-js/
IEEE
" » How I built a Multi-tenant SaaS product in Node.js." Muhamed Sufail | Sciencx [Online]. Available: https://www.scien.cx/2022/01/31/how-i-built-a-multi-tenant-saas-product-in-node-js/. [Accessed: ]
rf:citation
» How I built a Multi-tenant SaaS product in Node.js | Muhamed Sufail | Sciencx | https://www.scien.cx/2022/01/31/how-i-built-a-multi-tenant-saas-product-in-node-js/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.