mettre en place une architecture multi-tenant pour votre saas node.js avec postgresql
16/07/2025
architecture multi-tenant pour votre SaaS Node.js avec PostgreSQL
Dans ce tutoriel approfondi, nous allons implémenter une architecture multi-tenant sécurisée et performante pour une application SaaS basée sur Node.js et PostgreSQL. Vous apprendrez à isoler les données, à configurer le filtrage côté base de données et à intégrer tout cela dans votre code grâce à TypeORM.
1. Choisir le mode d’isolation des données
- Row-based tenancy (colonne tenant_id + Row Level Security)
- Schema-based tenancy (un schéma par client)
Nous privilégierons ici le « row-based » pour plus de simplicité et une maintenance allégée.
2. Préparer PostgreSQL (RLS et variable de session)
- Activer le RLS sur vos tables critiques :
ALTER TABLE users ENABLE ROW LEVEL SECURITY;
- Définir une politique d’isolation :
CREATE POLICY tenant_isolation ON users USING (tenant_id = current_setting('app.current_tenant')::int);
- Configurer la variable de session dans
postgresql.conf
:custom_variable_classes = 'app' app.current_tenant = ''
3. Installer et configurer TypeORM dans Node.js
npm install typeorm pg reflect-metadata
import { DataSource } from 'typeorm';
export const AppDataSource = new DataSource({
type: 'postgres',
host: process.env.DB_HOST,
port: +process.env.DB_PORT,
username: process.env.DB_USER,
password: process.env.DB_PASS,
database: process.env.DB_NAME,
entities: [__dirname + '/entities/*.js'],
synchronize: false,
logging: false,
});
Entité User avec tenant_id
import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm';
@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number;
@Column()
tenant_id: number;
@Column()
email: string;
@Column()
name: string;
}
4. Middleware Express pour injecter le tenant
import { Request, Response, NextFunction } from 'express';
import { AppDataSource } from './data-source';
export async function tenantMiddleware(req: Request, res: Response, next: NextFunction) {
const tenantId = req.headers['x-tenant-id'];
if (!tenantId) return res.status(400).send('Tenant ID missing');
// Avant chaque requête : définir la variable de session
await AppDataSource.manager.query(
`SET app.current_tenant = '${tenantId}';`
);
next();
}
Placez ce middleware avant vos routes protégées pour garantir l’isolation.
5. Vérifier l’isolation et mesurer les performances
- Testez l’accès interdits aux données d’un autre tenant : vous devriez obtenir zéro résultat.
- Surveillez le plan d’exécution :
Indice : créez un index multicolonne surEXPLAIN ANALYZE SELECT * FROM users WHERE tenant_id = 42;
(tenant_id, id)
pour réduire le temps de requête de 30 % en moyenne.
6. Bonnes pratiques et pièges à éviter
- Ne stockez jamais d’ID d’un tenant dans un token JWT sans vérification côté API.
- Utilisez un pool de connexions par tenant si vous dépassez 100 tenants pour éviter le « noisy neighbor ».
- Pensez à archiver les anciens tenants pour alléger la base (partitionnement).
Conclusion
Vous disposez désormais d’une base solide pour déployer une solution multi-tenant dans votre application SaaS. Les bénéfices : isolation forte, montée en charge maîtrisée et évolutivité.
Besoin d’un accompagnement pour industrialiser votre projet ? Contactez notre équipe.