Skip to content
Learni
Voir tous les tutoriels
Architecture

Comment implémenter le multi-tenancy en 2026

Read in English

Introduction

Le multi-tenancy permet à une même application de servir plusieurs clients (tenants) tout en isolant leurs données. Cette approche est essentielle pour les SaaS afin de réduire les coûts et simplifier la maintenance. Au lieu de déployer une instance par client, on utilise un identifiant de tenant pour filtrer les accès. Ce tutoriel vous guide pas à pas pour implémenter une solution simple et sécurisée avec Prisma et TypeScript.

Prérequis

  • Node.js 20+
  • Connaissances de base en TypeScript
  • PostgreSQL installé
  • npm ou yarn

Initialisation du projet

terminal
mkdir multi-tenancy-tutorial
cd multi-tenancy-tutorial
npm init -y
npm install express prisma @prisma/client
npx prisma init

Cette commande crée le projet et installe les dépendances nécessaires. Prisma gérera le schéma de base de données avec le champ tenantId pour l'isolation.

Schéma Prisma avec tenant

prisma/schema.prisma
generator client {
  provider = "prisma-client-js"
}

datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}

model User {
  id        Int    @id @default(autoincrement())
  email     String @unique
  tenantId  String
  name      String
}

Le modèle User inclut un tenantId obligatoire. Chaque requête filtrera automatiquement sur ce champ pour isoler les données par client.

Middleware d'isolation

src/middleware/tenant.ts
import { Request, Response, NextFunction } from 'express';

export const tenantMiddleware = (req: Request, res: Response, next: NextFunction) => {
  const tenantId = req.headers['x-tenant-id'] as string;
  if (!tenantId) {
    return res.status(400).json({ error: 'Tenant ID requis' });
  }
  (req as any).tenantId = tenantId;
  next();
};

Ce middleware extrait le tenantId depuis les headers et l'attache à la requête. Il garantit que chaque appel est associé à un tenant valide.

Configuration Prisma avec tenant

src/prisma.ts
import { PrismaClient } from '@prisma/client';

const prisma = new PrismaClient();

export const getTenantPrisma = (tenantId: string) => {
  return prisma.$extends({
    query: {
      user: {
        findMany: ({ args }) => {
          args.where = { ...args.where, tenantId };
          return args;
        }
      }
    }
  });
};

Cette extension Prisma injecte automatiquement le filtre tenantId sur les requêtes. Elle évite d'oublier le filtre manuellement et renforce la sécurité.

Route exemple avec isolation

src/routes/users.ts
import express from 'express';
import { tenantMiddleware } from '../middleware/tenant';
import { getTenantPrisma } from '../prisma';

const router = express.Router();
router.use(tenantMiddleware);

router.get('/', async (req, res) => {
  const tenantId = (req as any).tenantId;
  const prismaTenant = getTenantPrisma(tenantId);
  const users = await prismaTenant.user.findMany();
  res.json(users);
});

export default router;

La route applique le middleware puis utilise l'instance Prisma étendue. Les résultats sont automatiquement limités au tenant courant.

Bonnes pratiques

  • Toujours valider le tenantId en entrée
  • Utiliser des extensions Prisma pour centraliser la logique
  • Tester l'isolation avec plusieurs tenants
  • Ajouter des index sur tenantId pour les performances
  • Logger les accès par tenant pour l'audit

Erreurs courantes

  • Oublier le filtre tenantId dans une requête manuelle
  • Stocker le tenantId dans le corps au lieu des headers
  • Ne pas gérer les cas où le tenantId est absent
  • Ignorer les performances sur les tables volumineuses sans index

Pour aller plus loin

Approfondissez le sujet avec notre formation dédiée au multi-tenancy avancé. Découvrez nos formations Learni.