Multi-tenant Database Integration: Implementing Tenant Schema Isolation with Django Application

Describe the problem/error/question

I want to integrate n8n with my Django multi-tenant application where each tenant has their own database schema named tenant_[tenant_id]_schema. Each instance/tenant has their own users/admins, and I need to ensure that when someone accesses n8n, they can only interact with their own tenant’s database tables based on their tenant ID.

Specifically, I need:

  1. A way to dynamically restrict database access based on the user’s tenant ID

  2. Automatically prefix all database queries with the correct schema (tenant_[tenant_id]_schema)

  3. Maintain tenant isolation across all workflows and credentials

  4. Integrate with my existing Django authentication system

Has anyone implemented a similar multi-tenant architecture with n8n? What’s the recommended approach - custom nodes, middleware, or separate n8n instances per tenant? Are there enterprise features or community nodes that might help with this use case?

What is the error message (if any)?

No error yet, as I’m in the planning phase trying to determine the best implementation approach.

Please share your workflow

Not applicable as I’m seeking architectural guidance rather than troubleshooting a specific workflow.

Share the output returned by the last node

Not applicable.

Information on your n8n setup

  • n8n version: 1.82.0

  • Database PostgreSQL

  • n8n EXECUTIONS_PROCESS setting (default: own, main): Default

  • Running n8n via npx n8n

  • Operating system: Ubuntu Server

Hey, umardraz!

Let’s tackle this multi-tenant n8n integration step by step. I’ll break down your options and suggest a battle-tested architecture.

Key Requirements Recap:

  1. Tenant Isolation: Users interact only with their tenant_[id]_schema.
  2. Dynamic Credential Injection: Auto-prefix queries with the tenant schema.
  3. Django Auth Integration: Leverage existing user/tenant mappings.
  4. Scalability: Avoid separate n8n instances per tenant.

Recommended Architecture

Django App (Auth + Tenant Context)  
         │  
         ▼ (JWT/API Key)  
n8n Instance (Single)  
         │  
         ▼ (Tenant-aware Credentials)  
PostgreSQL (Schemas: tenant_1, tenant_2, ...)  

Step 1: Tenant Context Propagation

Method: Embed the tenant ID in requests to n8n via:

  • JWT Claims: Add tenant_id to the JWT during Django authentication.
  • API Key Suffixes: Generate n8n API keys like ak_[tenant_id]_[hash].

How n8n Uses This:

  • Webhook Workflows: Extract tenant_id from headers/path (e.g., /webhook/tenant_123/...).
  • CLI/API Triggers: Pass tenant_id as a parameter.

Step 2: Dynamic Schema Prefixing

Option A: Custom PostgreSQL Node

  1. Modify SQL Queries: Use expressions like:
    SET search_path TO tenant_{{ $tenantId }}_schema;  
    SELECT * FROM orders;  
    
  2. Create a Wrapper Node: Fork the PostgreSQL node to auto-inject search_path.

Option B: Middleware Proxy (Django Side)

  1. Intercept n8n DB Calls: Route requests to the correct schema using Django’s connection routing.
  2. Example Code:
    # settings.py  
    DATABASE_ROUTERS = ['path.to.TenantRouter']  
    
    # routers.py  
    class TenantRouter:  
        def db_for_read(self, model, **hints):  
            return 'tenant_' + request.tenant.id  # From JWT/session  
    

Step 3: Credential Isolation

Approach: Dynamic Credentials with Tenant ID

  1. Pre-Create Credentials: For each tenant, store PostgreSQL credentials in n8n’s encrypted DB with:
    • Name: PostgreSQL - Tenant 123
    • Schema: tenant_123_schema
  2. Map Users to Credentials: Use n8n’s Credentials (Enterprise) or a custom node to fetch credentials via Django’s API.

Step 4: Workflow Design

Template Structure:

Webhook (with tenant_id) → Function (Extract tenant_id) → PostgreSQL (Dynamic Schema)  

Critical Nodes:

  • Function Node (to parse tenant context):
    const tenantId = $request.headers['x-tenant-id'] || $input.body.tenant_id;  
    return { tenantId };  
    
  • PostgreSQL Node (schema set via expression):
    Schema: tenant_{{ $json.tenantId }}_schema  
    

Security Considerations

  • Row-Level Security (RLS): Add policies in PostgreSQL (e.g., CREATE POLICY tenant_isolation ON orders USING (tenant_id = current_setting('app.tenant_id'))).
  • Audit Logs: Enable n8n’s audit logs (Enterprise) to track tenant access.

Enterprise Features Worth Exploring

  • Workflow Permissions: Restrict workflows to specific tenants.
  • Multi-tenant Executions: Isolate execution data per tenant.

Alternatives to Avoid

  • Separate n8n Instances: Overhead and cost for 100s of tenants.
  • Raw SQL Concatenation: Prone to SQL injection.

Need More Details? Share how your Django app currently routes tenants (subdomains, paths, etc.), and I’ll refine the n8n-Django handoff! :rocket:

See ya!

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.