Multi-Tenancy and Team Self-Service
How gateway groups, roles, permission boundaries and labels combine so application teams can ship API configuration without being able to break production.
The question this page answers is the one a platform team asks after the gateway is running: how do I let application teams configure their own APIs without giving them the ability to take down someone else's?
API7 Gateway gives you four independent mechanisms. None of them is a tenancy model on its own; the model is how you combine them. This page is the synthesis — each mechanism's own page has the reference detail.
The four mechanisms
| Mechanism | What it isolates | What it does not do |
|---|---|---|
| Gateway groups | Runtime. A group has its own data planes, its own configuration and its own certificates. Configuration in one group cannot affect another. | Does not restrict who may change it. Any user with the right role can configure any group. |
| Roles and permission policies | Who may perform which action on which resource. | Grants are additive. A second role can widen access. |
| Permission boundaries | The ceiling on a user's permissions, whatever roles they later acquire. | Not a grant. A boundary alone gives no access. |
| Labels | Ownership metadata on resources, and the scope of a declarative sync. | Not a security control. A label does not stop anyone editing the resource. |
The distinction that matters: gateway groups are the blast-radius boundary; boundaries are the authority boundary; labels are the ownership boundary. Confusing the third for the first two is the common mistake — labels organise, they do not protect.
A model that works
1. One gateway group per environment, not per team
Give each environment its own group — production, staging, and a shared sandbox. Resist a group per team: every group needs its own data planes, its own certificates and its own licensed cores, so per-team groups multiply infrastructure and operational surface without adding isolation that boundaries and labels do not already give you.
Set the environment field to non_production on everything that is not production. Its data-plane cores then count against the non-production quota instead of your production entitlement — see License Management.
Use a group per team only when a team genuinely needs runtime isolation: a different data-plane version, a different network zone, or a compliance boundary that forbids shared infrastructure.
2. Give every team a boundary before you give them a role
A boundary is the only mechanism that survives someone later being granted a broader role. Set it first, as the standing organisational constraint:
curl -k "https://localhost:7443/api/users/${USER_ID}/boundaries" -X PUT \
-H "X-API-KEY: ${API_KEY}" \
-H "Content-Type: application/json" \
-d '["<policy-limiting-this-user-to-non-production>"]'Then grant day-to-day access with roles. The boundary means a mistaken role assignment cannot reach production — the user simply gets nothing extra until the boundary is changed deliberately.
This is what lets you delegate role assignment without delegating the ability to escalate.
3. Label every resource with its owner
Adopt one label key for ownership and apply it universally:
labels:
team: paymentsThis buys three things that nothing else does:
- Scoped declarative sync.
adc sync --label-selector team=paymentsmanages only that team's resources and leaves everything else alone, so several teams can run independent pipelines against the same gateway group. See Manage Gateway Configuration with GitOps. - Attribution in logs. Consumer labels can be written into access logs, which is what makes per-team traffic and error reporting possible — see Include Consumer Labels in Access Logs.
- Answering "who owns this route" during an incident, without asking in chat.
Do not use managed-by as your ownership key. ADC claims it, stamping managed-by: adc on everything it writes and overwriting whatever you set.
4. Make promotion the only path to production
Teams get write access to staging and no write access to production. Production changes arrive only by promoting a reviewed, version-controlled configuration:
adc sync -f gateway.yaml --gateway-group staging # the team's pipeline
adc sync -f gateway.yaml --gateway-group production # the platform pipeline, after approvalThe credential that can write to production belongs to the pipeline, not to a person. Combined with boundaries, this means no individual holds production write access at all — which is usually the control an auditor is actually asking about.
What teams can safely own
| Teams own | Platform owns | Why |
|---|---|---|
| Routes, services and upstreams for their own APIs | Gateway groups and data-plane lifecycle | Group changes affect every tenant |
| Their consumers and credentials | Global rules | A global rule applies to all traffic in the group |
| Per-route plugins: auth, rate limits, transformations | Certificates and TLS | Shared listener surface |
| Their own declarative file and pipeline | Roles, boundaries, licensing | Delegating these delegates escalation |
Global rules deserve emphasis. They apply to every request in a gateway group, so a team that can write them can affect every other team — and a declarative sync that omits them deletes them, including the prometheus rule that produces your traffic metrics. Keep global rules in the platform team's own pipeline and out of every team-scoped file.
Blast radius
What the worst plausible mistake reaches, if the model above is in place:
| Mistake | Reach |
|---|---|
| A team breaks its own route configuration | Their own APIs, in the group they can write to |
| A team's pipeline syncs a file missing half its resources | Their own labelled resources only, if the pipeline uses --label-selector |
A team's pipeline omits global_rules | The whole gateway group's global rules, because label scoping does not cover them. This is the reason global rules stay with the platform team |
| A user is given an over-broad role | Nothing, while their boundary holds |
| A team exhausts a shared rate-limit dictionary | Other tenants in the same group — dictionaries are per data plane, not per tenant |
That last row is the limit of the model: gateway groups isolate configuration, not resources. Teams sharing a group share worker processes, connection pools and shared-dictionary space. A team's traffic spike is felt by its neighbours. If a workload needs resource isolation rather than configuration isolation, it needs its own gateway group and its own data planes — see Shared Memory Sizing.
Related
- Design a Custom Role System — designing the roles themselves
- Create a Custom Role — the worked procedure
- Manage Gateway Groups
- Permission Policy Actions and Resources · Permission Policy Examples