Multi-tenant production-grade : isolation par schéma PostgreSQL, domaines vérifiés, white-label, admins multi-niveaux. Agences B2B.
Multi-Tenant B2B : Junyr vs Alternatives
En 2026, le multi-tenant est la norme pour les SaaS B2B. Mais tous les multi-tenants ne se valent pas. Junyr offre une isolation production-grade que les concurrents n'ont pas.
🏢 Le Multi-Tenant : Pourquoi C'est Critique
Définition
Multi-tenant = 1 instance logicielle partagée par plusieurs "tenants" (entreprises clientes), avec isolation des données.
Use Case B2B
Scénario : Agence propose Junyr en white-label à ses clients
Client A (Acme Corp) : 50 users, 10 Junyrs
Client B (Tech Inc) : 20 users, 5 Junyrs
Client C (Retail Ltd) : 100 users, 15 Junyrs
Requis :
✅ Isolation totale des données (Client A ne voit PAS Client B)
✅ Domaines custom (sales@acme.com, hr@techinc.com)
✅ Branding personnalisé (logo, couleurs)
✅ Admins par client (pas de super-admin unique)
✅ Facturation séparée (Stripe par client)
📊 Comparaison Multi-Tenant
| Aspect | Junyr | n8n | Make | Zapier |
|---|---|---|---|---|
| Architecture | Company-based (natif) | Workspaces (basique) | Organizations (limité) | Workspaces (limité) |
| Isolation données | ✅ Row-level security (PostgreSQL) | 🟡 Workspace ID (app-level) | 🟡 Org ID (app-level) | 🟡 Workspace ID (app-level) |
| Domaines email | ✅ Multi-domaines vérifiés | ❌ Aucun | ❌ Aucun | ❌ Aucun |
| Auto-registration | ✅ Via domaines vérifiés | ❌ Invites manuelles | ❌ Invites manuelles | ❌ Invites manuelles |
| White-label | ✅ Logo, couleurs, fonts | ❌ Marque n8n visible | ❌ Marque Make visible | ❌ Marque Zapier visible |
| Admins multi-niveaux | ✅ Super-admin + company-admin | 🟡 Owner + members | 🟡 Owner + members | 🟡 Owner + members |
| Facturation séparée | ✅ Stripe par company | 🟡 Manuelle | 🟡 Manuelle | 🟡 Manuelle |
🏗️ Architecture Junyr : Production-Grade
Database Schema Multi-Tenant
-- Companies (tenants)
CREATE TABLE business_companies (
id UUID PRIMARY KEY,
name VARCHAR(255) NOT NULL,
slug VARCHAR(100) UNIQUE,
siren VARCHAR(9),
siret VARCHAR(14),
created_at TIMESTAMP WITH TIME ZONE
);
-- Users appartiennent à une Company
CREATE TABLE users (
id UUID PRIMARY KEY,
email VARCHAR(255) UNIQUE NOT NULL,
company_id UUID REFERENCES business_companies(id),
role VARCHAR(50), -- 'user', 'company_admin', 'super_admin'
created_at TIMESTAMP WITH TIME ZONE
);
-- Domaines email vérifiés
CREATE TABLE company_domains (
id UUID PRIMARY KEY,
company_id UUID REFERENCES business_companies(id),
domain VARCHAR(255) NOT NULL,
is_verified BOOLEAN DEFAULT FALSE,
verified_at TIMESTAMP WITH TIME ZONE,
verification_method VARCHAR(20) -- 'dns', 'email', 'mx'
);
-- Admins par Company (junction table)
CREATE TABLE admin_companies (
user_id UUID REFERENCES users(id),
company_id UUID REFERENCES business_companies(id),
PRIMARY KEY (user_id, company_id)
);
-- Agents (Junyrs) appartiennent à un owner ET company
CREATE TABLE agents (
id UUID PRIMARY KEY,
user_id UUID REFERENCES users(id), -- Owner
company_id UUID REFERENCES business_companies(id), -- Isolation
name VARCHAR(255),
email VARCHAR(255),
created_at TIMESTAMP WITH TIME ZONE
);
-- Row-Level Security (RLS)
CREATE POLICY company_isolation ON agents
USING (company_id = current_setting('app.current_company')::UUID);
Isolation Garanties
| Type | Méthode | Détails |
|---|---|---|
| Données | Row-Level Security (PostgreSQL) | Politique RLS sur TOUTES les tables (users, agents, projects, messages) |
| API | Company ID validation | Middleware vérifie current_user.company_id sur chaque requête |
| Domain verification | Seuls domaines vérifiés peuvent auto-register | |
| Facturation | Stripe par company | subscription.company_id sépare les factures |
| UI | Company context | Sidebar affiche user.company.name (ex: "Acme Corp") |
🔐 Vérification Domaines : Sécurité Renforcée
Junyr : 2-Level Verification
┌─────────────────────────────────────────────────────────────────┐
│ NIVEAU 1 : Ownership (Prouver que vous possédez le domaine) │
├─────────────────────────────────────────────────────────────────┤
│ │
│ Méthode A : DNS TXT Record │
│ └─ Ajouter TXT : junyr-verify=abc123xyz │
│ → Vérifie propriété (enable auto-registration) │
│ │
│ Méthode B : Email Verification │
│ └─ Code 6 chiffres à admin@domain.com │
│ → Vérifie accès administratif │
│ │
│ ✅ Résultat : is_verified = TRUE │
│ → Users @domain.com peuvent auto-join company │
│ │
├─────────────────────────────────────────────────────────────────┤
│ NIVEAU 2 : Email Reception (Recevoir emails via Junyr) │
├─────────────────────────────────────────────────────────────────┤
│ │
│ Méthode : MX Record Configuration │
│ └─ MX 10 mail.junyr.app │
│ └─ TXT "v=spf1 mx include:junyr.app -all" │
│ │
│ ✅ Résultat : email_reception_ready = TRUE │
│ → Junyrs peuvent recevoir emails à sales@domain.com │
│ │
└─────────────────────────────────────────────────────────────────┘
n8n/Make/Zapier : Aucune Vérification
❌ Pas de système de domaines
❌ Pas de vérification ownership
❌ Pas d'auto-registration sécurisée
❌ Invites manuelles uniquement (risque email typo)
Problème Sécurité :
Scénario n8n :
1. Admin invite user@acme.com (typo : user@acne.com)
2. Email va à mauvaise personne
3. Mauvaise personne accepte l'invite
4. Accès workspace avec données sensibles
VS Junyr :
1. Domain acme.com vérifié (DNS TXT + code email)
2. user@acme.com auto-join après validation email
3. user@acne.com BLOQUÉ (domaine non vérifié)
4. Zéro risque d'accès non autorisé
👥 Auto-Registration : UX Supérieure
Junyr : Auto-Join Sécurisé
Workflow auto-registration :
1. User visite https://junyr.app/signup
2. Entre email : john@acme.com
3. Backend vérifie :
✅ Domain "acme.com" existe dans company_domains
✅ is_verified = TRUE
4. User créé avec company_id = Acme Corp
5. Email confirmation envoyé
6. User clique lien → Auto-join Acme Corp
Résultat :
✅ John voit immédiatement les Junyrs de l'équipe
✅ John peut collaborer avec collègues
✅ Aucune action admin requise
n8n/Make/Zapier : Invites Manuelles
Workflow invites :
1. Admin ouvre "Team Settings"
2. Clique "Invite Member"
3. Entre manuellement email : john@acme.com
4. System envoie email invite
5. John reçoit email, clique lien
6. John accepte invite
7. Admin doit assigner rôle manuellement
Problèmes :
❌ Admin doit inviter CHAQUE user (scaling difficile)
❌ Risque typo email (user@acne.com vs user@acme.com)
❌ Pas d'onboarding automatisé
❌ John ne voit rien avant invite
🎨 White-Label : Branding Complet
Junyr : Personnalisation Totale
Settings > Branding (company-level) :
✅ Logo upload (PNG/JPG/SVG, max 2MB)
✅ Primary color (#0066cc)
✅ Secondary color (#f5f5f5)
✅ Font family (Inter, Roboto, Poppins, etc.)
Appliqué à :
- PDF exports (header logo + couleurs)
- Excel exports (styles personnalisés)
- Email signatures (logo + couleurs)
- UI theme (primary color dans boutons, badges)
Use case : Agence white-label
→ Client A voit logo Acme + bleu
→ Client B voit logo Tech Inc + vert
→ Jamais la marque "Junyr" visible
n8n/Make/Zapier : Marque Visible
❌ Logo n8n/Make/Zapier dans UI (non modifiable)
❌ Branding dans emails notifications
❌ Footer "Powered by n8n/Make/Zapier"
→ Impossible de revendre en white-label
🔑 Admins Multi-Niveaux
Junyr : 3 Rôles Hiérarchiques
┌─────────────────────────────────────────────────────────────────┐
│ HIERARCHY ROLES │
├─────────────────────────────────────────────────────────────────┤
│ │
│ SUPER_ADMIN (Junyr Team) │
│ ├─ Gère TOUTES les companies │
│ ├─ Accès pricing, AI models, platform config │
│ └─ Peut devenir admin de n'importe quelle company │
│ ↓ │
│ COMPANY_ADMIN (Client A, Client B, etc.) │
│ ├─ Gère SA company uniquement │
│ ├─ Invite users, manage Junyrs, configure domains │
│ └─ Voit TOUS les Junyrs de sa company (pas juste les siens) │
│ ↓ │
│ USER (Membres équipe) │
│ ├─ Voit les Junyrs de sa company │
│ ├─ Peut interagir avec ses propres Junyrs │
│ └─ Pas de gestion admin │
│ │
└─────────────────────────────────────────────────────────────────┘
n8n/Make/Zapier : 2 Rôles Basiques
OWNER (1 seul par workspace)
├─ Tous les droits
└─ Peut inviter members
MEMBER
├─ Peut voir workflows
└─ Peut exécuter (selon permissions)
❌ Pas de multi-level admin
❌ Pas de délégation granulaire
❌ Scaling difficile (1 owner bottleneck)
💳 Facturation Séparée : Stripe Multi-Tenant
Junyr : Stripe Customer Par Company
# Backend : stripe_service.py
async def create_plan_subscription_checkout(
company_id: str,
plan_id: str,
user_email: str
):
# 1. Récupérer company
company = await db.fetchrow(
"SELECT * FROM business_companies WHERE id = $1",
company_id
)
# 2. Créer Stripe Customer (1 par company)
customer = stripe.Customer.create(
email=user_email,
metadata={
"company_id": company_id,
"company_name": company["name"]
}
)
# 3. Créer checkout session
session = stripe.checkout.Session.create(
customer=customer.id,
line_items=[{
"price": PLAN_PRICES[plan_id],
"quantity": 1
}],
mode="subscription",
metadata={"company_id": company_id} # Tracking
)
# 4. Stocker subscription
await db.execute(
"INSERT INTO subscriptions (company_id, stripe_subscription_id, ...)"
)
Résultat :
- ✅ 1 facture Stripe par company (séparation claire)
- ✅ Metadata
company_idpour tracking - ✅ Webhooks Stripe → update status par company
n8n/Make/Zapier : Facturation Manuelle
❌ Pas de Stripe multi-tenant natif
❌ Admin doit créer subscriptions manuellement
❌ Facturation agrégée (impossible de séparer par client)
→ Complexe pour revente white-label
📊 Cas d'Usage Réel : Agence B2B
Scénario : Agence Propose Junyr à 10 Clients
Avec Junyr (Multi-Tenant Natif)
Setup (1 fois) :
1. Agence crée 10 companies dans Junyr Admin
- Acme Corp (client A)
- Tech Inc (client B)
- ...
- Retail Ltd (client J)
2. Vérifier domaines clients :
- acme.com (DNS TXT + MX)
- techinc.com (DNS TXT + MX)
- ...
3. Configurer white-label branding par client
4. Créer Stripe subscriptions par company
Utilisation (automatique) :
✅ Users clients auto-join via email @domain.com
✅ Isolation totale (Acme ne voit PAS Tech Inc)
✅ Facturation séparée (10 factures Stripe)
✅ Branding personnalisé (10 logos différents)
Maintenance : 0 heures/mois (automatique)
Avec n8n/Make/Zapier (Pas Multi-Tenant)
Setup (laborieux) :
1. Créer 10 workspaces séparées
- Workspace "Acme Corp"
- Workspace "Tech Inc"
- ...
2. Inviter TOUS les users manuellement (1 par 1)
- john@acme.com → invite manuelle
- jane@acme.com → invite manuelle
- ...
→ 100+ invites si 10 users/client
3. ❌ Impossible de white-label (marque visible)
4. ❌ Facturation manuelle par workspace
Utilisation (manuelle) :
❌ Admin doit inviter chaque nouveau user
❌ Pas d'auto-registration sécurisée
❌ Marque n8n/Make/Zapier visible (pas white-label)
❌ Facturation complexe (10 workspaces à gérer)
Maintenance : 10-20 heures/mois (invites, support)
Gain Junyr : 10-20 heures/mois + white-label possible
🎯 Matrice de Choix
| Use Case | Recommandation | Pourquoi |
|---|---|---|
| Agence white-label | Junyr | Multi-tenant natif + branding |
| Startup (1 équipe) | n8n/Make/Zapier | Workspaces suffisants |
| SaaS B2B multi-clients | Junyr | Isolation + auto-registration |
| Freelance | Junyr Personal | 1 company = suffisant |
| Grande entreprise multi-BU | Junyr Enterprise | Multi-admin + isolation |
💡 Conclusion
Le multi-tenant n'est pas juste une "feature bonus". Pour les agences et SaaS B2B, c'est une architecture critique.
n8n/Make/Zapier : Workspaces basiques (1 équipe par workspace) Junyr : Multi-tenant production-grade (isolation, domaines, branding, facturation)
Les bénéfices Junyr :
- ✅ Isolation row-level (sécurité PostgreSQL)
- ✅ Domaines vérifiés (auto-registration sécurisée)
- ✅ White-label complet (logo, couleurs, fonts)
- ✅ Facturation Stripe séparée par company
- ✅ Admins multi-niveaux (super-admin, company-admin, user)
- ✅ Gain 10-20h/mois maintenance (agences)
Si vous revendez à des clients : Junyr est structurellement supérieur.
📈 Aller Plus Loin
- Essayer Junyr gratuitement (3 jours)
- Documentation : Multi-Tenant Setup
- Case Study : Agence White-Label
Junyr Team
Plateforme IA
L'equipe Junyr conçoit des outils d'IA qui permettent aux TPE/PME européennes de recruter, former et piloter des agents IA autonomes pour leurs tâches quotidiennes.
Articles liés
Email Professionnel Intégré : L'Avantage Junyr
Stalwart mail server intégré vs intégrations Gmail externes. Email-to-Task temps réel, domaines custom, archivage S3.
Lire l’article →Workflow 3-Step : La Garantie Qualité de Junyr
Query Check, Execution, Verification : le workflow en 3 étapes qui réduit significativement les erreurs et garantit la qualité.
Lire l’article →Universal Inbox : Vue 360° vs Données Éparpillées
JMAP Resources unifie emails, documents, datasets. Late binding 3-tier, Project 360 View. Fini la chasse au trésor dans 5 apps.
Lire l’article →