Skip to Content

Tenant and Namespace Management

Ark uses Kubernetes namespaces as tenants. Each namespace is an isolated environment with its own agents, models, tools, and queries. Isolation is enforced at the Kubernetes level via RBAC.

Setting Up a Tenant

Set your kubectl context to the target namespace and use the Ark CLI to install:

kubectl create namespace tenant-a kubectl config set-context --current --namespace=tenant-a ark install ark-tenant ark install ark-broker ark install ark-api ark install ark-dashboard

This installs the tenant chart (service account, roles, builtin tools), the broker (per-tenant message and session storage), the API layer, and the dashboard. You can then open the dashboard with:

ark dashboard

The Ark CLI uses your current kubectl context namespace. You can also install the charts directly with Helm — see the Deploying Ark guide.

Cross-Tenant Access

By default, tenants are fully isolated. A user accessing Tenant A’s dashboard cannot see resources in Tenant B. A cluster administrator can grant cross-tenant access using standard Kubernetes RBAC.

Example: Two Tenants with Cross-Access

Install two full tenants:

kubectl create namespace tenant-a kubectl config set-context --current --namespace=tenant-a ark install ark-tenant ark install ark-broker ark install ark-api ark install ark-dashboard kubectl create namespace tenant-b kubectl config set-context --current --namespace=tenant-b ark install ark-tenant ark install ark-broker ark install ark-api ark install ark-dashboard

At this point both tenants are fully isolated. To grant Tenant A access to Tenant B’s resources, apply a RoleBinding:

apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: tenant-a-access namespace: tenant-b subjects: - kind: ServiceAccount name: ark-api-sa namespace: tenant-a roleRef: kind: Role name: ark-tenant-role apiGroup: rbac.authorization.k8s.io

A user on Tenant A’s dashboard can now view and manage Tenant B’s resources by adding ?namespace=tenant-b to the URL.

Without the RoleBinding, the API returns a 403 error when attempting to access another tenant’s resources.

Broker storage isolation

The cross-tenant isolation above applies to Kubernetes resources and is enforced by RBAC. The broker’s message storage is a separate concern. The broker is a per-tenant component — each tenant namespace runs its own broker — while only the controller is a cluster-wide singleton.

When the broker uses the default in-memory message store, each broker pod holds its own messages, so isolation follows the deployment. With the Postgres message backend (backends.message: postgres) the messages table has no tenant_id column and no row-level security — its columns are sequence_number, conversation_id, query_id, message, created_at, and expires_at. Data isolation between tenants therefore depends entirely on the deployment, not on the data.

Each per-tenant broker must point at its own database (or at least its own schema) with its own credentials. Do not share one DATABASE_URL across brokers of different tenants — their messages would be commingled in the same messages table with no way to separate them after the fact.

The same applies to the Redis chunks backend (backends.chunk: redis): chunk streams carry no per-tenant separation, and REDIS_KEY_PREFIX namespaces keys but is not an isolation boundary. Each per-tenant broker must point at its own Redis instance (or keyspace) with its own credentials — never share one REDIS_URL across brokers of different tenants. Traces, events, and sessions remain in memory regardless of backend.

See Message backend (Postgres) and Chunk backend (Redis) for backend configuration.

Developing with Tenants

During development, use devspace to deploy into a tenant namespace:

devspace dev -n tenant-a

Or set your kubectl context and use the CLI:

kubectl config set-context --current --namespace=tenant-a ark dashboard

Add ?namespace=tenant-b to the URL to view another tenant’s resources.

Last updated on