Creating a Multi-Tenant Application with NestJS and PostgreSQL
In the world of web development, multi-tenant applications are becoming increasingly popular. They allow a single instance of an application to serve multiple customers, known as tenants. This is particularly beneficial for SaaS (Software as a Service) providers, enabling them to save on resources and streamline updates. In this article, we will explore how to create a multi-tenant application using NestJS, a powerful Node.js framework, and PostgreSQL, a robust relational database.
What is a Multi-Tenant Application?
A multi-tenant application is designed to serve multiple users or organizations (tenants) from a single codebase and database. The primary goal is to isolate the data and configurations for each tenant while sharing the underlying infrastructure. This can be achieved through various architectural patterns, including:
- Database-per-tenant: Each tenant has its own database.
- Schema-per-tenant: Each tenant has its own schema within a shared database.
- Shared schema: All tenants share the same database and schema, with tenant-specific data distinguished by a tenant identifier.
For this tutorial, we will focus on the shared schema approach, which is cost-effective and easier to manage for smaller applications.
Use Cases for Multi-Tenant Applications
Multi-tenant applications are particularly useful in various scenarios:
- SaaS products: Applications that provide services to multiple organizations (e.g., CRM, project management tools).
- E-commerce platforms: Marketplaces that host multiple sellers.
- Educational platforms: Learning management systems that cater to different institutions.
With these use cases in mind, let’s dive into building a multi-tenant application using NestJS and PostgreSQL.
Prerequisites
Before we start coding, ensure you have the following installed:
- Node.js (version 14.x or higher)
- PostgreSQL (version 12.x or higher)
- NestJS CLI
You can install the NestJS CLI using npm:
npm install -g @nestjs/cli
Step-by-Step Guide to Building a Multi-Tenant Application
1. Setting Up Your NestJS Project
First, create a new NestJS project:
nest new multi-tenant-app
cd multi-tenant-app
Next, install the necessary dependencies for PostgreSQL and TypeORM:
npm install @nestjs/typeorm typeorm pg
2. Configuring TypeORM
In your app.module.ts
, configure TypeORM to connect to your PostgreSQL database. Modify the module to include TypeORM configuration:
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { AppController } from './app.controller';
import { AppService } from './app.service';
@Module({
imports: [
TypeOrmModule.forRoot({
type: 'postgres',
host: 'localhost',
port: 5432,
username: 'your_username',
password: 'your_password',
database: 'your_database',
entities: [__dirname + '/../**/*.entity{.ts,.js}'],
synchronize: true,
}),
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
3. Creating the Tenant Entity
Now, let’s create a tenant entity. In your src
directory, create a folder called tenants
and add a file named tenant.entity.ts
:
import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm';
@Entity()
export class Tenant {
@PrimaryGeneratedColumn()
id: number;
@Column({ unique: true })
name: string;
@Column()
databaseConnection: string; // Store tenant-specific connection info if needed.
}
4. Creating the Tenant Service and Controller
In the tenants
folder, create tenants.service.ts
and tenants.controller.ts
files:
tenants.service.ts:
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { Tenant } from './tenant.entity';
@Injectable()
export class TenantsService {
constructor(
@InjectRepository(Tenant)
private tenantsRepository: Repository<Tenant>,
) {}
async create(name: string): Promise<Tenant> {
const tenant = this.tenantsRepository.create({ name });
return this.tenantsRepository.save(tenant);
}
async findAll(): Promise<Tenant[]> {
return this.tenantsRepository.find();
}
}
tenants.controller.ts:
import { Controller, Post, Body, Get } from '@nestjs/common';
import { TenantsService } from './tenants.service';
import { Tenant } from './tenant.entity';
@Controller('tenants')
export class TenantsController {
constructor(private readonly tenantsService: TenantsService) {}
@Post()
create(@Body('name') name: string): Promise<Tenant> {
return this.tenantsService.create(name);
}
@Get()
findAll(): Promise<Tenant[]> {
return this.tenantsService.findAll();
}
}
5. Registering the Tenant Module
Create a new module file tenants.module.ts
and register the service and controller:
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { TenantsController } from './tenants.controller';
import { TenantsService } from './tenants.service';
import { Tenant } from './tenant.entity';
@Module({
imports: [TypeOrmModule.forFeature([Tenant])],
controllers: [TenantsController],
providers: [TenantsService],
})
export class TenantsModule {}
Finally, import the TenantsModule
in your app.module.ts
:
import { TenantsModule } from './tenants/tenants.module';
@Module({
imports: [
TypeOrmModule.forRoot({
// ... existing configuration
}),
TenantsModule,
],
// ... existing controllers and providers
})
export class AppModule {}
6. Running the Application
You can now run your NestJS application:
npm run start
You can test your multi-tenant API by using Postman or any API client. Create a new tenant by sending a POST request to http://localhost:3000/tenants
with a JSON body:
{
"name": "Tenant1"
}
7. Conclusion and Next Steps
Congratulations! You have successfully created a basic multi-tenant application using NestJS and PostgreSQL. This setup provides a solid foundation for building scalable and maintainable applications.
Next Steps
- Implement authentication and authorization to secure tenant data.
- Explore more complex data models and relationships.
- Consider implementing a tenant-specific middleware for request handling.
By following the steps outlined in this article, you’re now equipped to build sophisticated multi-tenant applications that can meet the needs of various clients. Happy coding!