Sharing a single vector database account across multiple projects feels efficient at first. You have one place to log in, one set of credentials to manage, one billing line to track. But without deliberate organization, a shared workspace accumulates problems over time: teams can see each other’s data when they should not, a key compromised in one project becomes a problem for all of them, and nobody has a clear picture of which collections belong to which project.
The goal is not to eliminate sharing — it is to structure it so that each project operates as if it has its own isolated environment, even when the underlying infrastructure is shared.
The Core Problem with Unstructured Sharing
When multiple projects share a workspace without any organizational structure, three problems tend to develop.
Data visibility bleeds across projects. Without access controls scoped to specific collections, a developer on one project can query or modify data that belongs to another. This is usually accidental — someone uses the wrong collection name, runs a broad query, or inherits permissions from a shared key that were appropriate for a different context.
A single security perimeter covers everything. If one project’s key is compromised, an attacker has access to all projects in the workspace. There is no containment because there is no isolation.
Organizational changes require broad updates. When a developer moves from one project to another, their permissions need to change. If access is not project-scoped, there is no clean way to do this — you either give them access to too much or you rotate shared credentials that other people are depending on.
Structured sharing solves all three by adding boundaries that are invisible in normal operation but meaningful when something goes wrong.
Organizing by Collections
The most natural unit of organization in a vector database is the collection (sometimes called an index). Each project should own a set of collections, and access should be granted at the collection level rather than at the workspace level.
This means a developer on Project A can read and write to Project A’s collections but cannot touch Project B’s collections, even if both exist in the same account. The access restriction is enforced by the database’s permission system, not by convention or trust.
Collection-level access control requires a role-based permission system. Most managed vector database platforms support this in some form: you define roles that map to specific collections and operations, then assign those roles to credentials.
Multi-Tenancy as a Data Isolation Layer
Collection-level separation works well when projects have distinct data structures. When multiple projects share the same collection structure — for example, multiple customers of a SaaS product all storing documents of the same type — collection-level isolation alone is not enough. You need data-level isolation within a shared collection.
Multi-tenancy is the mechanism for this. It allows a single collection to store data for multiple tenants in complete isolation: one tenant cannot read another’s data, and each tenant’s data can be independently managed (backed up, deleted, scaled). From the outside, the collection looks like one thing. From the inside, each tenant’s data is a separate partition.
When combined with access controls, multi-tenancy lets you scope permissions not just to a collection but to a specific tenant within a collection. A credential granted access to tenant A’s data cannot read tenant B’s data in the same collection, even if both are in the same workspace.
Environment Separation
Projects at different stages of development should not share the same cluster. Development work that involves schema changes, bulk deletions, or performance testing can interfere with a production workload running on the same infrastructure.
The cleaner model is a separate cluster for each environment — development, staging, production — with separate credentials for each. This adds some cost and management overhead, but it provides a hard boundary that prevents development accidents from affecting production data. Credentials for each environment are stored as environment variables, so the same codebase connects to the right cluster depending on where it is running.
Keeping Large Teams Organized
For large organizations with multiple teams working across multiple projects, manual key management does not scale. The overhead of creating keys, assigning roles, revoking access, and keeping everything in sync with organizational changes becomes its own operational burden.
Integrating with an identity provider (IdP) addresses this at the root. When group membership in the IdP maps to roles in the vector database, access changes happen automatically when someone joins or leaves a team in the IdP. No separate step in the vector database console is required. This is particularly valuable for projects with regular team rotation, where the cost of manual access management would otherwise be significant.
Weaviate: Organizing a Shared Account in Practice
Here is how each organizational layer maps to Weaviate specifically.
Collection-Scoped RBAC Roles
Create a role that restricts access to one project’s collections:
from weaviate.classes.rbac import Permissions
client.roles.create(
role_name="ProjectA_Reader",
permissions=[
Permissions.data(collection="ProjectACollection", read=True),
],
)
A user assigned ProjectA_Reader can only read from ProjectACollection. They have no visibility into any other collection in the account, even if they know its name.
Tenant-Scoped Permissions for Multi-Tenant Collections
When multiple projects share a collection structure, scope roles to specific tenants:
client.roles.create(
role_name="ProjectA_Clinician",
permissions=[
Permissions.data(collection="PatientRecords", tenant="project_a", read=True),
],
)
Wildcards are supported for flexible tenant scoping:
Permissions.data(collection="PatientRecords", tenant="project_*", read=True)
This grants access to all tenants matching the pattern — useful when a project has multiple sub-tenants that all need the same access level, without updating the role each time a new sub-tenant is added.
One Key Per User or Service
Give each developer and each service its own API key, scoped to the role appropriate for their work. This makes revocation clean: removing a developer’s access means disabling their key, not rotating a shared credential that affects everyone else.
OIDC Group Mapping for Large Teams
For organizations with an identity provider, map IdP groups to Weaviate roles so that project team membership automatically controls access:
client.groups.oidc.assign_roles(
group_id="ProjectA-Team",
role_names=["ProjectA_Reader"],
)
When someone moves from Project A to Project B in the IdP, their Weaviate access updates automatically on next connection — no manual intervention in the console required.
Separate Clusters Per Environment
Development, staging, and production each get their own Weaviate cluster, with their own credentials stored as environment variables:
export WEAVIATE_URL="https://your-cluster-url"
export WEAVIATE_API_KEY="your-api-key"
The application code does not change between environments — only the environment variables do.
Quick Reference
| Concern | Solution |
|---|---|
| Project data isolation | Multi-tenancy + tenant-scoped RBAC roles |
| Team access separation | Custom roles per project collection |
| Credential hygiene | One API key per user or service |
| Large team management | OIDC group to role mapping |
| Environment separation | Separate clusters per environment |
| Visibility and compliance | Audit logs for all authorization decisions |