skip to content

You run one Argo CD instance for a dozen teams. How do you decide what each team may self-serve through projects and RBAC, and when would you give a team its own Argo CD instance instead?

level: principalimportance: should knowfreq 38%

answer

  1. the project is the tenant, and it is platform-owned
  2. rights inside a project versus rights over projects
  3. tokens scoped to a project role, never admin
  4. instances split trust, projects split authorization

basics

~20 s

Delegate inside the AppProject and keep the project itself privileged: teams get project roles, tokens and sync rights over their own applications, while the platform owns project definitions and cluster registrations. A separate instance is warranted when the isolation or upgrade coupling of a shared control plane is unacceptable.

solid answer

~50 s

The design rule is that the AppProject is the tenant unit and its definition is a platform artifact. Teams get rights *inside* a project: `applications` actions scoped to `<project>/*` in `argocd-rbac-cm`, or roles declared in the project's own `spec.roles` with `proj:<project>:<role>` subjects, plus project-scoped tokens for their CI. What stays with the platform is `projects, update`, `clusters` and `repositories` — anything that could widen a fence or reach another tenant. Beyond that, decide two things deliberately: whether teams may author Applications at all or only receive them from a generated set, and how project definitions are reviewed, since they are the real security boundary. A separate Argo CD instance is worth its operational cost when a tenant must not share the control plane's credentials or blast radius — a regulated environment, an untrusted tenant, or a team whose upgrade and outage schedule cannot be coupled to everyone else's. The cost is real: more instances mean more upgrades, more SSO wiring and a fragmented view of the fleet.

go deeper

for a junior

Know that a shared Argo CD instance separates teams with AppProjects and RBAC roles, not with separate installations, and that admin rights are not the normal grant.

for a middle

Be able to describe the delegated set concretely — application actions scoped to the project, project roles, project-scoped tokens — and name what stays privileged, starting with editing projects themselves.

for a senior

Show you have operated this: token issuance and revocation, disabling the local admin account after SSO, deciding on exec access, and keeping project definitions reviewed rather than hand-edited.

for a principal

Own the split decision with named triggers — credential blast radius, upgrade coupling, scale — state the operational cost of each additional instance, and design how tenant projects are generated so policy changes land uniformly.

## The thing you are actually dividing An Argo CD instance holds credentials for every cluster it manages and applies whatever its repositories say. In tenancy terms it is a shared privileged actor. Multi-team design is the question of how much of that actor each team gets to steer, and the answer is expressed almost entirely through AppProjects and the RBAC policy. ## What is safe to delegate Self-service is worth designing for, because a platform team that hand-edits YAML for every tenant becomes the bottleneck GitOps was supposed to remove. Three things delegate cleanly: **Operating their own applications.** Grant `applications` actions — `get`, `sync`, `action/*`, `logs` — scoped to `<project>/*`. This is the daily work: see the diff, trigger a sync, restart a workload, read logs. **Defining their own sub-roles.** An AppProject's `spec.roles` lets the tenant express finer structure — an on-call role that may sync production, a read role for everyone else — and the mechanism is safe because a project role's policies can only reference objects inside that project. Bind those roles to identity-provider groups with the role's `groups` list rather than issuing credentials. **Automating from CI.** `argocd proj role create-token` issues a JWT bound to a project role, so a pipeline can trigger a sync without holding an admin credential. Give the token an expiry, record it in the project's `jwtTokens`, and know that deleting the entry revokes it — a project token is far better than the alternative you will otherwise find in a pipeline, which is the local `admin` password. ## What must not be delegated The complements of the above are exactly the things that let a tenant escape: - **`projects, update`** — the fence editor. A tenant who can widen `destinations`, `sourceRepos` or `clusterResourceWhitelist` has no fence. - **`clusters` and `repositories`** — registering a new cluster or a credentialed repository adds reach and secrets to the shared instance. - **`accounts` and the local `admin`** — disable `admin` once SSO works so every action is attributable. - **`exec`** — the ability to open a shell into a workload pod from the UI, which is genuinely useful and a genuine bypass of the deployment path; grant it deliberately, per project, or not at all. A related decision is `policy.default`. Leaving it empty denies unmatched users, which is right for a shared instance; setting `role:readonly` gives every employee a view of every tenant's applications, which some organisations want for transparency and others consider a leak. ## Making the fences maintainable A dozen hand-written AppProjects drift. Two habits keep them honest. First, keep project definitions in a repository with review rules of their own and apply them declaratively — they are control-plane configuration and deserve at least the review discipline of production code. Second, template them: projects for tenants that look alike should be generated from a small tenant record rather than copied, so that a policy change lands everywhere at once and an accidental `'*'` is visible as a diff. ## When one instance stops being right Projects give you authorization isolation, not failure or credential isolation. Split when: - **Credential blast radius is unacceptable.** A compromise of the shared instance reaches every registered cluster. If one tenant is regulated, externally operated, or genuinely untrusted, its clusters should not be registered next to everyone else's. - **Upgrade and outage coupling is unacceptable.** One instance means one upgrade window and one incident affecting every team's ability to deploy. Some organisations can absorb that; a tenant with a hard release calendar may not. - **Scale hurts.** A single instance reconciling many thousands of applications becomes an operational object in its own right, with its own tuning and its own noisy-neighbour effects between tenants. The cost is honest and should be stated: every extra instance is another SSO integration, another RBAC policy to keep consistent, another upgrade, and the loss of a single place to answer "what is deployed where". The usual landing point is few instances rather than one or many — commonly split along a trust or environment boundary, with projects doing the tenancy work inside each one. ## What a strong answer sounds like Name the AppProject as the tenancy unit and the split between rights inside a project and rights over projects. Give the concrete delegated set and the withheld set. Then treat the separate-instance question as a tradeoff with named triggers — credential blast radius, upgrade coupling, scale — rather than a preference, and admit the operational cost of the split you are proposing.

  • How would you give a team's CI pipeline the ability to sync its own applications without an admin credential?
    Define a role in the team's AppProject whose policies cover only `<project>/*`, then issue a token for it with `argocd proj role create-token`, with an expiry. The token's subject is `proj:<project>:<role>`, so its reach is bounded by the project definition rather than by trust in the pipeline. Revocation is deleting the token entry from the project's `jwtTokens`.
  • A team asks for permission to edit its own AppProject so it can stop filing tickets. How do you respond?
    Say no to `projects, update` and fix the underlying friction instead. Most requests are for a new namespace or repository, so template the projects from a tenant record the team can raise a pull request against, with the platform reviewing. They get self-service through review rather than through a permission that erases their fence, and the change is auditable as a diff.

saying these in an interview costs you the question

  • Grants role:admin because per-project rules felt tedious
  • Lets tenants edit their own AppProjects to avoid tickets
  • Puts the local admin password into team CI pipelines
  • Treats one instance per team as free isolation with no cost
  • Assumes projects isolate failure and credentials, not just authorization

context