“Project-level RBAC for multi-team and multi-client isolation” sounds like one feature request. It is two, and they are not solved by the same mechanism. One is access control: deciding who inside your organization can read or edit which workflows and credentials. The other is isolation: keeping one tenant’s data, failures, and resource usage away from another’s. n8n’s project roles answer the first question well. They do almost nothing for the second. Treating them as interchangeable is how multi-client n8n designs end up either over-built or dangerously under-isolated.
This targets self-hosted n8n. As of June 2026 the current stable release is 2.23.4 (published 2026-06-05), with the 2.25.x line still on the next and beta channels. The examples run on PostgreSQL 18 and Redis 8 with Docker Compose, on a single VPS or a queue-mode cluster. Every feature claim below was checked against the n8n documentation at the time of writing; where the docs gate a feature by version, that version is named inline.
Two problems hiding in one request
Pull the request apart before designing anything.
Access control governs what a user can do inside an instance they already share with others. The relevant questions are: can this person edit that workflow, see those credentials, publish to production. n8n answers these with project membership and roles.
Isolation governs blast radius and separation across a trust boundary. The relevant questions are different: if one tenant’s workflow runs away with CPU, does another tenant slow down. If one tenant’s credentials leak, whose data is exposed. Can a malicious or compromised tenant read another tenant’s data at all. Roles do not answer any of these, because every project in one instance runs on the same process, the same database, and the same secret-handling layer.
The rule of thumb for the rest of this article: multiple teams inside one organization is an access-control problem, and one instance with roles is the right tool. Multiple external clients, or any compliance, data-residency, or hard blast-radius requirement, is an isolation problem, and the right tool is deployment topology, not a finer role.
What you get, and on which plan
Settle the licensing reality before any pattern, because it decides whether the RBAC half of this article applies to you at all.
Role-based access control is not in the community edition; the RBAC documentation states it as a plan fact: “RBAC is available on all plans except the Community edition.” A community instance has no projects at all: one Owner account that sees and edits everything, and Members who see only what they created themselves. Team projects, the built-in Project Admin, Editor, and Viewer roles, custom roles, SSO and SAML, LDAP, and log streaming all sit behind a paid plan; the community edition features page lists what registering a free community instance unlocks and what stays paid. I walked the full two-axis permission model and the community cliff in the permissions deep-dive; this article only needs the parts that bear on isolation.
The gating is finer than “paid versus free,” and it differs per role. Per the role types documentation, the Project Editor role is available on Pro Cloud and Self-hosted Enterprise, while the Project Viewer role is available only on Self-hosted Enterprise and Cloud Enterprise. Custom project roles are a Self-hosted Enterprise and Cloud Enterprise feature, and per the custom roles documentation they exist since n8n 1.122.0 (released November 24, 2025). The pricing page also lists a Business self-hosted tier with shared projects and SSO, but the role-types and custom-roles pages gate the Editor, Viewer, and custom roles to the plans above. If a specific role is the load-bearing part of your design, confirm it against those two pages for your exact plan before you commit to anything.
Two numbers people ask for are not worth asserting from memory. The docs do not publish a fixed count of projects per plan (“different plans have different numbers of projects and roles” is all the RBAC page commits to), and Self-hosted Enterprise pricing is quote-based. Check the pricing page for current plan composition, project limits, and cost rather than trusting a figure from a third-party blog.
Note: if you run community n8n on a VPS, the entire RBAC half of this topic does not apply to your setup. You have one Owner, no projects, and no roles to assign. The honest answer to “how do I set up project RBAC on community” is: you upgrade to a paid plan, or you run separate instances.
The permission model: account types versus project roles
n8n’s RBAC is two-tier, and you have to hold both tiers in your head at once. The custom roles documentation states the split directly: instance roles span the entire n8n instance and all projects, while project roles apply within a specific project.
Account types are instance-level. Owner, Admin, and Member span the entire instance and all projects. An account has exactly one type.
Role types are project-level. Project Admin, Project Editor, Project Viewer, and any custom roles apply within a single project. The same account can hold different roles in different projects: Editor in the team’s own project, Viewer in a neighboring team’s project, no membership at all elsewhere.
The three built-in project roles, per the role-types page, run from most to least privileged. A Project Admin manages project settings and members and has full read, create, update, and delete over the workflows, credentials, and executions in that project. A Project Editor has the same read, create, update, and delete over resources but cannot manage the project itself or its members. A Project Viewer is read-only and, notably, cannot manually execute a workflow.
Here is the detail that the entire isolation argument later depends on. Instance Owner and Admin accounts can view and edit every project, every workflow, and every credential, regardless of whether they are members of those projects. The permission matrix in the account types documentation spells it out: view and share all workflows, view, edit, and share all credentials, and view all projects are all Owner and Admin rows. No project can hide its contents from a super-admin. Inside one instance there is always an account that sees everything.
Mapping teams to projects: practical RBAC patterns
For multiple teams inside one organization, the model is straightforward: make each team, or each team-and-environment, a project, then assign least-privilege roles. Three patterns cover most needs.
The first is team per project. This is the simplest unit of access. Each team gets a project; people are Editors in their own team’s project and, where cross-team visibility helps, Viewers in another. Creating a project, adding and removing members, and moving resources are all covered in the projects documentation.
The second is separation of duties through custom roles. The built-in roles are coarse: an Editor can do everything to everything in the project. Custom roles let you split responsibilities by granting only specific scopes. The custom roles documentation lists the catalog: workflow scopes (workflow:create, workflow:read, workflow:update, workflow:execute, workflow:publish, workflow:delete, workflow:move, plus a data-redaction pair), the full set of credential:* scopes up to credential:share and credential:unshare, project scopes (project:read, project:update, project:delete), folder, execution, and data table scopes, externalSecret:list for using external secrets in credentials, and the secret-vault scopes (externalSecretsProvider:create, :read, :update, :delete, :sync), which are available from n8n 2.13.0. Two pairing rules change what a checkbox grants: <resource>:read also grants the matching list scope, and workflow:publish also grants workflow:unpublish. The docs also ship ready-made role examples - a workflow developer, a credential manager, a secrets user, and a workflow publisher - that you can copy and adjust. From those scopes you can build, for instance:
- A workflow author who can create and update workflows but holds no credential scopes.
- A credential manager who holds the
credential:*scopes plus read-only workflow access. - A publisher who can read and publish workflows but not edit them: the documented example grants
workflow:read,workflow:publish,credential:read, andproject:read, with noworkflow:update.
workflow:execute deserves its own sentence. It is a distinct scope, separate from editing and publishing, so you can grant run-only access: a user who can execute a sensitive workflow without being able to modify it. The built-in roles do not cover that combination - a Viewer cannot run anything - and custom roles are an Enterprise feature, so this common compliance request is an Enterprise answer.
The third pattern is environment separation. If you keep development and production as distinct projects, scope publish and execute rights tightly so that the people who build in dev are not the same people who can publish or run in prod. n8n has a dedicated source control and environments feature for promoting work between environments; if you intend to lean on it as the promotion mechanism rather than just modeling environments as plain projects, confirm its current behavior in those docs before you commit a process to it.
In all three patterns, remember the plan gate from the previous section: Viewer and custom roles are Self-hosted Enterprise features. State the gate wherever you hand a pattern to your team, so nobody designs around a role their license does not include.
Where project isolation stops
This is the hinge of the whole topic. Projects are an access-control boundary. They are not an isolation boundary. Everything in one instance, across every project, shares the resources below, and each shared resource carries a consequence that no role can undo.
One encryption scheme for all credentials. n8n’s encryption key rotation documentation describes the model precisely. N8N_ENCRYPTION_KEY is the instance master key, set at deployment, and it never changes; n8n uses it only to protect the data encryption keys. The data encryption key is the one that directly encrypts credential data and the one you can rotate, stored encrypted in the database under the master key. Both layers are instance-wide. There is no per-project key and no per-tenant key. Every credential in every project is protected by the same scheme, so projects give you no cryptographic separation whatsoever.
One database, one queue, one worker pool. All projects share the same PostgreSQL database. In queue mode, they also share the same Redis queue and the same pool of workers. The queue mode documentation describes the flow: the main process passes an execution ID to Redis, a worker in the pool picks it up, and that worker uses the ID to fetch the workflow and credentials from the shared database and decrypt them with the shared N8N_ENCRYPTION_KEY. There is no documented routing of a project’s jobs to a project’s own workers; the queue is common.
A minimal queue-mode stack makes the point concrete:
services: postgres: image: postgres:18-alpine restart: unless-stopped environment: POSTGRES_USER: n8n POSTGRES_PASSWORD: REPLACE_WITH_STRONG_DB_PASSWORD POSTGRES_DB: n8n volumes: - postgres_data:/var/lib/postgresql/data
redis: image: redis:8-alpine restart: unless-stopped
n8n-main: image: n8nio/n8n:2.23.4 restart: unless-stopped command: start depends_on: - postgres - redis ports: - "5678:5678" environment: EXECUTIONS_MODE: queue N8N_ENCRYPTION_KEY: REPLACE_WITH_32_PLUS_CHAR_RANDOM_KEY DB_TYPE: postgresdb DB_POSTGRESDB_HOST: postgres DB_POSTGRESDB_DATABASE: n8n DB_POSTGRESDB_USER: n8n DB_POSTGRESDB_PASSWORD: REPLACE_WITH_STRONG_DB_PASSWORD QUEUE_BULL_REDIS_HOST: redis volumes: - n8n_data:/home/node/.n8n
n8n-worker: image: n8nio/n8n:2.23.4 restart: unless-stopped command: worker depends_on: - postgres - redis environment: EXECUTIONS_MODE: queue N8N_ENCRYPTION_KEY: REPLACE_WITH_32_PLUS_CHAR_RANDOM_KEY DB_TYPE: postgresdb DB_POSTGRESDB_HOST: postgres DB_POSTGRESDB_DATABASE: n8n DB_POSTGRESDB_USER: n8n DB_POSTGRESDB_PASSWORD: REPLACE_WITH_STRONG_DB_PASSWORD QUEUE_BULL_REDIS_HOST: redis volumes: - n8n_data:/home/node/.n8n
volumes: postgres_data: n8n_data:The encryption key, the database connection, and the Redis host are identical on the main process and the worker, and they have to be: the queue-mode docs require the main instance’s encryption key to be shared with every worker so workers can decrypt credentials from the database. A worker with a different key starts fine and fails the moment a workflow needs a credential, which is a quiet and confusing failure mode. There is nowhere in this file to scope the key, the database, or the queue to a project. That absence is the isolation boundary, drawn in YAML. In production you would supply the encryption key and database password through Docker secrets or a secured environment file rather than inline values, but the sharing is the same either way.
One global concurrency budget. Per the concurrency control documentation, N8N_CONCURRENCY_PRODUCTION_LIMIT caps how many production executions run at once (disabled by default in regular mode), and in queue mode each worker takes jobs up to its --concurrency flag, which defaults to 10. There is no per-project or per-workflow concurrency limit. The number you see at the top of a project’s or workflow’s executions tab is the same instance-wide limit displayed in that context, not a per-project allocation. A heavy or runaway workflow in one project consumes capacity from the shared pool and degrades every other project. The way to get a guaranteed slice of capacity is to run a separate instance.
Variables and tags are global. The role-types page says it directly: variables and tags are not affected by RBAC; they are global across the n8n instance. Do not put anything project-confidential in a variable or a tag and expect a role to hide it.
A super-admin who sees everything. From the permission model above: instance Owner and Admin accounts read and edit all projects. There is no configuration that walls a project off from them.
A shared webhook host. Every project is served by the same instance on the same host and port. There is no per-project network boundary, no per-project domain, and no per-project ingress isolation unless you build it outside n8n.
Read that list as a whole and the conclusion is forced: a single instance is one trust boundary. Projects partition who can act within it. They do not partition the cryptography, the data store, the execution capacity, the global objects, the administrative view, or the network surface.
Multi-client isolation: choose the deployment model, not a finer role
n8n has no native multi-tenancy. The community consensus says so plainly, but you do not have to take the consensus on faith, because the official facts from the previous section force the conclusion: a shared key, a shared queue, a global concurrency budget, and an all-seeing super-admin are exactly the things a tenancy boundary must not share. So the second problem is solved by topology. Here are the options, ordered by isolation strength.
Hard isolation, which is the recommendation for external clients, compliance, or data residency, means one n8n instance per client. Each instance gets its own process, its own PostgreSQL database, its own N8N_ENCRYPTION_KEY, its own Redis if it runs in queue mode, and its own webhook host or domain. Concretely, you take the stack above and stamp it out once per client, changing the encryption key, the database, and the host each time, and orchestrate the set with Docker Compose projects or Kubernetes namespaces. The per-instance baseline - backups, monitoring, upgrades - is the same production setup you would run for a single instance, multiplied. This is the only option that gives separate blast radius, separate keys, separate execution capacity, and clean audit boundaries. The cost is operational overhead: more instances to deploy, update, monitor, and back up. That overhead is the price of real isolation, and for external clients it is the correct price to pay.
Soft isolation inside one instance is acceptable only for trusted, internal, multi-team use. This is the Enterprise projects and RBAC story from the earlier sections. It is useful for keeping teams out of each other’s workflows and credentials under one organization’s trust boundary. It is not a client-isolation boundary, for every reason in the previous section.
A middle pattern exists, and it must be flagged as not natively supported: routing specific workloads to dedicated worker pools, combined with per-tenant credential or secret namespaces. Treat this as a community pattern to verify, not a documented n8n feature. By default, workers pull from a shared queue, so without custom work this gives you neither a hard security boundary nor a guaranteed capacity boundary. If you go down this road, prove the behavior in your own environment and do not present it to a client as isolation.
Decision matrix: which model for which boundary
| Scenario | Recommended model | Why |
|---|---|---|
| Several teams inside one organization (trusted) | Single Self-hosted Enterprise instance, one project per team, least-privilege roles | One trust boundary; access control is the actual need, and shared infrastructure is acceptable |
| Internal teams plus a few sensitive or noisy workloads | Single instance with isolated credentials, and consider moving the sensitive or noisy workload to its own instance | Limits credential exposure and noisy-neighbor impact while staying within one trust boundary |
| External clients, or compliance, data residency, or strong blast-radius needs | Separate n8n instance per client | Only topology gives separate data, keys, execution capacity, and audit boundaries |
| You are on community edition and need any of the above | For in-org RBAC, upgrade to a paid plan; for client isolation, run a separate community instance per boundary | Community has neither RBAC nor multi-tenancy, so the answer is upgrade or replicate |
Operating it: governance and the documented pitfalls
RBAC is only worth having if it is auditable and if you avoid the sharing traps the docs warn about.
The governance pairing matters in a review. SSO (SAML, OIDC, LDAP) and log streaming, which carries the n8n.audit event group, are paid features in the same neighborhood as project roles, and they are what make your RBAC defensible to a vendor-security or compliance reviewer. Roles without an audit trail rarely survive that conversation.
Three pitfalls are worth committing to memory.
Moving a workflow or credential between projects revokes all existing individual sharing. The projects documentation flags this directly: moving workflows or credentials removes all existing sharing, and that can break other workflows relying on the shared resource. You re-grant through the destination project. When moving a workflow, n8n offers to move its associated credentials if you have permission to share them.
External secrets for project roles are opt-in and gated by version. Per the external secrets documentation, from n8n 2.13.0 an instance owner or admin can turn on external-secret access for project editors and admins under Settings > External Secrets, with the toggle “Enable external secrets for project roles.” Before 2.13.0, using external secrets in a project required an instance owner or admin to be a member of that project; with the toggle off, only instance owners and admins can resolve external secrets at runtime. The practical trap follows from that: a credential that uses a secret expression, created by an instance owner, can pass a preview in the editor and then fail in production when it runs under a project role that cannot resolve the secret. External secrets are an Enterprise feature, support self-hosted HashiCorp Vault (not the HCP service), AWS Secrets Manager, Azure Key Vault, GCP Secret Manager, and 1Password Connect Server, and resolve plaintext values only, not JSON objects. Where each kind of secret belongs in the first place - environment variables versus the credential store versus an external vault - is its own article.
Variables and tags leak across projects, as established in the isolation section. This is not a bug to work around; it is the documented behavior. Keep project-confidential data out of both.
The whole topic collapses to one decision you can defend. If the people you are separating share a trust boundary, use Enterprise project RBAC inside one instance and spend your effort on least-privilege roles. If they do not, give each one its own instance, and do not let a role stand in for a boundary it was never built to be.