Multi-tenancy operations
Multi-tenancy provides data isolation. Each tenant is stored on a separate shard. Data stored in one tenant is not visible to another tenant. If your application serves many different users, multi-tenancy keeps their data private and makes database operations more efficient.
Enable multi-tenancy
Section titled “Enable multi-tenancy”Multi-tenancy is disabled by default. To enable multi-tenancy, set multiTenancyConfigin the collection definition:
from weaviate.classes.config import Configuremulti_collection = client.collections.create( name="MultiTenancyCollection", # Enable multi-tenancy on the new collection multi_tenancy_config=Configure.multi_tenancy(enabled=True))const result = await client.collections.create({ name: collectionName, multiTenancy: weaviate.configure.multiTenancy({ enabled: true })})client.Schema().ClassCreator(). WithClass(&models.Class{ Class: "MultiTenancyCollection", MultiTenancyConfig: &models.MultiTenancyConfig{ Enabled: true, }, }). Do(ctx)client.collections.create("MultiTenancyCollection", col -> col
.multiTenancy(mt -> mt.enabled(true).autoTenantCreation(true)));await client.Collections.Create(
new CollectionCreateParams
{
Name = "MultiTenancyCollection",
MultiTenancyConfig = new MultiTenancyConfig { Enabled = true },
}
);Automatically add new tenants
Section titled “Automatically add new tenants”By default, Weaviate returns an error if you try to insert an object into a non-existent tenant. To change this behavior so Weaviate creates a new tenant, set autoTenantCreation to true in the collection definition.
The auto-tenant feature is available from v1.25.0 for batch imports, and from v1.25.2 for single object insertions as well.
Set autoTenantCreation when you create the collection, or reconfigure the collection to update the setting as needed.
Automatic tenant creation is useful when you import a large number of objects. Be cautious if your data is likely to have small inconsistencies or typos. For example, the names TenantOne, tenantOne, and TenntOne will create three different tenants.
Create a collection
Section titled “Create a collection”from weaviate.classes.config import Configuremulti_collection = client.collections.create( name="CollectionWithAutoMTEnabled", # Enable automatic tenant creation multi_tenancy_config=Configure.multi_tenancy( enabled=True, auto_tenant_creation=True ))const result = await client.collections.create({ name: collectionName, multiTenancy: weaviate.configure.multiTenancy({ enabled: true, autoTenantCreation: true })})func createClassWithAutoTenantEnabled(ctx context.Context, client *weaviate.Client) {
class := &models.Class{
Class: "AutoTenantEnabledOnCreate",
Properties: []*models.Property{
{Name: "textProp", DataType: []string{"text"}},
},
MultiTenancyConfig: &models.MultiTenancyConfig{
Enabled: true,
AutoTenantCreation: true,
},
}
err := client.Schema().ClassCreator().WithClass(class).Do(ctx)
if err != nil {
log.Fatalf("create class: %v", err)
}
}client.collections.create("CollectionWithAutoMTEnabled",
col -> col.multiTenancy(mt -> mt.autoTenantCreation(true)));await client.Collections.Create(
new CollectionCreateParams
{
Name = "CollectionWithAutoMTEnabled",
MultiTenancyConfig = new MultiTenancyConfig
{
Enabled = true,
AutoTenantCreation = true,
},
}
);curl localhost:8080/v1/schema -H 'content-type:application/json' -d \'{ "class": "Customer", "properties": [ { "name": "customer_name", "dataType": ["text"] }, { "name": "customer_category", "dataType": ["text"] } ], "multiTenancyConfig": { "enabled": true, "autoTenantCreation": true }}'Update a collection
Section titled “Update a collection”Use the client to update the auto-tenant creation setting. Auto-tenant is only available for batch inserts.
from weaviate.classes.config import Reconfigurecollection = client.collections.use(collection_name)collection.config.update( multi_tenancy_config=Reconfigure.multi_tenancy(auto_tenant_creation=True))import { reconfigure } from 'weaviate-client';existing, err := client.Schema().ClassGetter().
WithClassName(class.Class).Do(ctx)
if err != nil {
log.Fatalf("get existing class %q: %v", class.Class, err)
}
existing.MultiTenancyConfig.AutoTenantCreation = true
err = client.Schema().ClassUpdater().WithClass(existing).Do(ctx)
if err != nil {
log.Fatalf("enable autotenant: %v", err)
}CollectionHandle<Map<String, Object>> collection =
client.collections.use(collectionName);
collection.config
.update(col -> col.multiTenancy(mt -> mt.autoTenantCreation(true)));var collection = client.Collections.Use(collectionName);
await collection.Config.Update(c =>
{
c.MultiTenancyConfig.AutoTenantCreation = true;
});Add new tenants manually
Section titled “Add new tenants manually”To add tenants to a collection, specify the collection and the new tenants. Optionally, specify the tenant activity status as ACTIVE(available, default), INACTIVE (not available, on disk), or OFFLOADED (not available, offloaded to cloud).
This example adds tenantA to the MultiTenancyCollection collection:
Additional information
Tenant status is available from Weaviate 1.21 onwards.
from weaviate.classes.tenants import Tenant# Add two tenants to the collectionmulti_collection.tenants.create( tenants=[ Tenant(name="tenantA"), Tenant(name="tenantB"), ])const multiCollection = client.collections.use(collectionName);await multiCollection.tenants.create([ { name: 'tenantA' }, { name: 'tenantB' }])client.Schema().TenantsCreator(). WithClassName("MultiTenancyCollection"). WithTenants(models.Tenant{Name: "tenantA"}, models.Tenant{Name: "tenantB"}). Do(ctx)collection.tenants.create(Tenant.active("tenantA"),
Tenant.active("tenantB"));await collection.Tenants.Create(["tenantA", "tenantB"]);List all tenants
Section titled “List all tenants”List existing tenants in a collection.
This example lists the tenants in the MultiTenancyCollection collection:
multi_collection = client.collections.use("MultiTenancyCollection")tenants = multi_collection.tenants.get()print(tenants)const multiCollection = client.collections.use(collectionName);let tenants = await multiCollection.tenants.get()console.log(tenants)tenants, err := client.Schema().TenantsGetter().
WithClassName("MultiTenancyCollection").
Do(ctx)List<Tenant> tenants = collection.tenants.get();
System.out.println(tenants);var tenants = await collection.Tenants.List();
foreach (var t in tenants)
Console.WriteLine(t.Name);Get tenants by name
Section titled “Get tenants by name”Get tenants from a collection by name. Note that non-existent tenant names are ignored in the response.
This example returns tenantA and tenantB from the MultiTenancyCollection collection:
multi_collection = client.collections.use("MultiTenancyCollection")tenant_names = ["tenantA", "tenantB", "nonExistentTenant"] # `nonExistentTenant`` does not exist and will be ignoredtenants_response = multi_collection.tenants.get_by_names(tenant_names)for k, v in tenants_response.items(): print(k, v)const multiCollection = client.collections.use(collectionName);const tenants = await multiCollection.tenants.getByNames(['tenantA', 'tenantB'])console.log(tenants)List<String> tenantNames =
Arrays.asList("tenantA", "tenantB", "nonExistentTenant");
List<Tenant> tenants = collection.tenants.get(tenantNames);
System.out.println(tenants);var tenantNames = new[] { "tenantA", "tenantB", "nonExistentTenant" };
var tenants = await collection.Tenants.List(tenantNames);
foreach (var t in tenants)
Console.WriteLine(t.Name);Get one tenant
Section titled “Get one tenant”Get a particular tenant from a collection.
This example returns a tenant from the MultiTenancyCollection collection:
multi_collection = client.collections.use("MultiTenancyCollection")tenant_obj = multi_collection.tenants.get_by_name(tenant_name)print(tenant_obj.name)const multiCollection = client.collections.use(collectionName);const tenant = await multiCollection.tenants.getByName('tenantA')console.log(tenant)String tenantName = "tenantA";
Optional<Tenant> tenant = collection.tenants.get(tenantName);
System.out.println(tenant);string tenantName = "tenantA";
var tenant = await collection.Tenants.Get(tenantName);
Console.WriteLine(tenant?.Name);Delete tenants
Section titled “Delete tenants”To delete tenants from a collection, specify the collection (e.g. MultiTenancyCollection) and the tenants (tenantB and tenantX). The delete operation ignores tenant names if a named tenant is not a part of the collection.
multi_collection = client.collections.use("MultiTenancyCollection")# Remove a list of tenants - tenantX will be ignored.multi_collection.tenants.remove(["tenantB", "tenantX"])const multiCollection = client.collections.use(collectionName);await multiCollection.tenants.remove([ { name: 'tenantB' }, { name: 'tenantX' } // tenantX will be ignored])client.Schema().TenantsDeleter().
WithClassName("MultiTenancyCollection").
WithTenants("tenantB", "tenantX"). // tenantX will be ignored
Do(ctx)collection.tenants.delete(Arrays.asList("tenantB", "tenantX"));await collection.Tenants.Delete(new[] { "tenantB", "tenantX" });Manage tenant states
Section titled “Manage tenant states”Change a tenant state between ACTIVE, INACTIVE, and OFFLOADED.
from weaviate.classes.tenants import Tenant, TenantActivityStatusmulti_collection = client.collections.use("MultiTenancyCollection")multi_collection.tenants.update(tenants=[ Tenant( name="tenantA", activity_status=TenantActivityStatus.ACTIVE # INACTIVE, OFFLOADED )])const multiCollection = client.collections.use(collectionName)await multiCollection.tenants.update({ name: 'tenantA', activityStatus: 'ACTIVE' // 'INACTIVE', 'OFFLOADED'})String tenantName = "tenantA";
CollectionHandle<Map<String, Object>> collection =
client.collections.use(collectionName);
collection.tenants.deactivate(tenantName);
collection.tenants.activate(tenantName);
// collection.tenants.offload(tenantName); // Requires S3 offload modulestring tenantName = "tenantA";
var multiCollection = client.Collections.Use(collectionName);
// Deactivate
await multiCollection.Tenants.Update([
new Tenant { Name = tenantName, Status = TenantActivityStatus.Inactive },
]);
// Activate
await multiCollection.Tenants.Update([
new Tenant { Name = tenantName, Status = TenantActivityStatus.Active },
]);
// Offloading requires S3/warm/cold configurationCRUD operations
Section titled “CRUD operations”Multi-tenancy collections require tenant name (e.g. tenantA) with each CRUD operation, as shown in the object creation example below.
multi_collection = client.collections.use("MultiTenancyCollection")# Get collection specific to the required tenantmulti_tenantA = multi_collection.with_tenant("tenantA")# Insert an object to tenantAobject_id = multi_tenantA.data.insert( properties={ "question": "This vector DB is OSS & supports automatic property type inference on import" })const multiCollection = client.collections.use(collectionName);const multiTenantA = multiCollection.withTenant('tenantA')await multiTenantA.data.insert({ question: 'This vector DB is OSS & supports automatic property type inference on import'})object, err := client.Data().Creator(). WithClassName("MultiTenancyCollection"). // The class to which the object will be added WithProperties(map[string]interface{}{ "question": "This vector DB is OSS & supports automatic property type inference on import", }). WithTenant("tenantA"). // The tenant to which the object will be added Do(ctx)var jeopardy = client.collections.use("JeopardyQuestion").withTenant("tenantA");var uuid = jeopardy.data.insert(Map.of("question", "This vector DB is OSS & supports automatic property type inference on import")) .uuid();System.out.println(uuid); // the return value is the object's UUIDvar jeopardy = client.Collections.Use("JeopardyQuestion").WithTenant("tenantA");var uuid = await jeopardy.Data.Insert( new { question = "This vector DB is OSS & supports automatic property type inference on import", });Console.WriteLine(uuid); // the return value is the object's UUIDSearch queries
Section titled “Search queries”Multi-tenancy collections require the tenant name (e.g. tenantA) with each Get and Aggregate query operation.
multi_collection = client.collections.use("MultiTenancyCollection")# Get collection specific to the required tenantmulti_tenantA = multi_collection.with_tenant("tenantA")# Query tenantAresult = multi_tenantA.query.fetch_objects( limit=2,)print(result.objects[0].properties)const multiCollection = client.collections.use(collectionName);const multiTenantA = multiCollection.withTenant('tenantA')const objectA = await multiTenantA.query.fetchObjects({ limit: 2})console.log(objectA.objects)result, err := client.GraphQL().Get(). WithClassName("MultiTenancyCollection"). WithFields(graphql.Field{Name: "question"}). WithTenant("tenantA"). Do(ctx)var jeopardy = client.collections.use("JeopardyQuestion").withTenant("tenantA");var response = jeopardy.query.fetchObjects(c -> c.limit(2));for (var o : response.objects()) { System.out.println(o.properties());}var jeopardy = client.Collections.Use("JeopardyQuestion").WithTenant("tenantA");var response = await jeopardy.Query.FetchObjects(limit: 2);foreach (var o in response.Objects){ Console.WriteLine(JsonSerializer.Serialize(o.Properties));}Cross-references
Section titled “Cross-references”A cross-reference can be added from a multi-tenancy collection object to:
- A non-multi-tenancy collection object, or
- An object belonging to the same tenant.
Multi-tenancy collections require the tenant name (e.g. tenantA) when creating, updating or deleting cross-references.
from weaviate.classes.config import ReferencePropertymulti_collection = client.collections.use("MultiTenancyCollection")# Add the cross-reference property to the multi-tenancy classmulti_collection.config.add_reference( ReferenceProperty( name="hasCategory", target_collection="JeopardyCategory" ))# Get collection specific to the required tenantmulti_tenantA = multi_collection.with_tenant(tenant="tenantA")# Add reference from MultiTenancyCollection object to a JeopardyCategory objectmulti_tenantA.data.reference_add( from_uuid=object_id, # MultiTenancyCollection object id (a Jeopardy question) from_property="hasCategory", to=category_id # JeopardyCategory id)const multiCollection = client.collections.use(collectionName);// Add the cross-reference property to the multi-tenancy classawait multiCollection.config.addReference({ name: 'hasCategory', targetCollection: 'JeopardyCategory'})const multiTenantA = multiCollection.withTenant('tenantA')await multiTenantA.data.referenceAdd({ fromUuid: objectId, fromProperty: 'hasCategory', to: categoryId})// Add the cross-reference property to the multi-tenancy classclient.Schema().PropertyCreator(). WithClassName("MultiTenancyCollection"). WithProperty(&models.Property{ Name: "hasCategory", DataType: []string{"JeopardyCategory"}, }). Do(ctx)// Create the cross-reference from MultiTenancyCollection object to the JeopardyCategory objectclient.Data().ReferenceCreator(). WithClassName("MultiTenancyCollection"). WithTenant("tenantA"). WithID(object.ID.String()). // MultiTenancyCollection object id (a Jeopardy question) WithReferenceProperty("hasCategory"). WithReference(client.Data().ReferencePayloadBuilder(). WithClassName("JeopardyCategory"). WithID(category.ID.String()). Payload()). Do(ctx)client.collections.create("JeopardyCategory");
client.collections.create("MultiTenancyCollection",
col -> col.multiTenancy(mt -> mt.enabled(true)));
var categoryCollection = client.collections.use("JeopardyCategory");
var categoryUuid =
categoryCollection.data.insert(Map.of("name", "Test Category"));
var multiCollection = client.collections.use("MultiTenancyCollection");
multiCollection.tenants.create(Tenant.active("tenantA"));
var multiTenantA = multiCollection.withTenant("tenantA");
var referenceObject =
multiTenantA.data.insert(Map.of("title", "Object in Tenant A"));
String objectId = referenceObject.uuid();
multiCollection.config.addReference("hasCategory", "JeopardyCategory");
multiTenantA.data.referenceAdd(objectId, // from_uuid
"hasCategory", // from_property
ObjectReference.object(categoryUuid) // to
);var multiCollection = client.Collections.Use("MultiTenancyCollection");await multiCollection.Tenants.Create(["tenantA"]);// Add the cross-reference property to the multi-tenancy classawait multiCollection.Config.AddReference( Property.Reference("hasCategory", "JeopardyCategory"));// Get collection specific to the required tenantvar multiTenantA = multiCollection.WithTenant("tenantA");// Insert an object to tenantAvar objectId = await multiTenantA.Data.Insert( new { question = "This vector DB is OSS & supports automatic property type inference on import", });// Add reference from MultiTenancyCollection object to a JeopardyCategory objectawait multiTenantA.Data.ReferenceAdd( from: objectId, // MultiTenancyCollection object id (a Jeopardy question) fromProperty: "hasCategory", to: categoryId // JeopardyCategory id);Backups
Section titled “Backups”Related pages
Section titled “Related pages”- Connect to Weaviate
- How to: Manage collections
- References: REST API: Schema
- Concepts: Data Structure: Multi-tenancy
Questions and feedback
Section titled “Questions and feedback”Have a question or feedback? Here's how to reach us.