Hi everyone,
I’m designing a more advanced n8n setup where multiple clients/tenants use the same workflow logic, but each tenant has:
• Different API credentials
• Different rate limits
• Separate databases/storage
• Different execution volumes
Right now, I’m debating between:
One shared workflow + dynamic credentials/config
vs
Separate workflow per tenant
The shared approach is easier to maintain, but I’m worried about:
• Credential isolation
• Rate-limit collisions
• One tenant affecting another’s executions
• Debugging and observability at scale
The separate-workflow approach gives isolation, but managing updates across many workflows feels painful.
I’m also considering:
• Central config DB per tenant
• Dynamic credential injection
• Queue-based execution routing
• Separate worker instances for high-volume tenants
Describe the problem/error/question
For people running n8n in production with multiple Workflows :
What architecture has worked best?
How do you handle isolation vs maintainability?
Any patterns you’d strongly avoid?
What is the error message (if any)?
Please share your workflow
(Select the nodes on your canvas and use the keyboard shortcuts CMD+C/CTRL+C and CMD+V/CTRL+V to copy and paste the workflow.)
Share the output returned by the last node
Information on your n8n setup
- n8n version:
- Database (default: SQLite):
- n8n EXECUTIONS_PROCESS setting (default: own, main):
- Running n8n via (Docker, npm, n8n cloud, desktop app):
- Operating system:
Hi @Keira_Becky A hybrid setup usually works best.
Instead of creating a separate workflow
Most people use: One shared workflow + separate config for each tenant
So the workflow stays the same, but each tenant has their own:
• API keys
• Database
• Rate limits
• Settings
loaded dynamically using a tenant_id.
Why this is better: It’s Easier to maintain
You only update one workflow
Less duplication
Even with shared workflows, try to keep:
• Credentials
• Queues
• Rate limits
• Execution data
separate per tenant to avoid one customer affecting another.
For very large tenants, some teams use:
Dedicated worker / queue
so heavy traffic from one tenant doesn’t slow everyone else down.
Really well-framed question, @Keira_Becky! This is one of those architecture decisions that’s easy to get wrong early and painful to refactor later.
Niffzy’s hybrid approach is the right starting point. Here’s how I’d think through each of your concerns in practice:
Credential isolation: In n8n you can’t truly inject credentials dynamically at runtime (credentials are bound at workflow build time). The workaround most teams use is storing API keys in a central config table (Postgres or even a simple Google Sheet) keyed by tenant_id, then fetching them at the start of each run via an HTTP Request or database node and passing them forward as variables to subsequent nodes that accept custom auth headers. Not perfect but works well for most REST APIs.
Rate-limit collisions: The Queue Mode is your best friend here. Run n8n with EXECUTIONS_MODE=queue and Redis, then assign different concurrency limits per workflow or use multiple workers. You can even tag high-volume tenants to a dedicated worker.
One tenant affecting others: With queue mode + concurrency limits per workflow, this is mostly solved. For extra safety, consider a separate n8n instance (or n8n Cloud project) for your largest/most critical tenants.
Debugging at scale: Tag every execution with a tenant_id in your first node output. That way you can filter execution logs by tenant easily. Some teams also write a log entry to a central DB at the start and end of each run.
Pattern to strongly avoid: Storing per-tenant state in static variables or workflow-level memory. It bleeds between executions unpredictably.
Happy to go deeper on any of these if useful!