Skip to main content
Weaviate Docs (migrated from docs.weaviate.io) Docs

Search documentation

Type to search this documentation.

On this pageOverview

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.

Multi-tenancy is disabled by default. To enable multi-tenancy, set multiTenancyConfigin the collection definition:

Python
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))
JavaScript/TypeScript
const result = await client.collections.create({  name: collectionName,  multiTenancy: weaviate.configure.multiTenancy({ enabled: true })})
Go
client.Schema().ClassCreator().  WithClass(&models.Class{    Class: "MultiTenancyCollection",    MultiTenancyConfig: &models.MultiTenancyConfig{      Enabled: true,    },  }).  Do(ctx)
Java
client.collections.create("MultiTenancyCollection", col -> col
    .multiTenancy(mt -> mt.enabled(true).autoTenantCreation(true)));
C#
await client.Collections.Create(
    new CollectionCreateParams
    {
        Name = "MultiTenancyCollection",
        MultiTenancyConfig = new MultiTenancyConfig { Enabled = true },
    }
);

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.

Python
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    ))
JavaScript/TypeScript
const result = await client.collections.create({  name: collectionName,  multiTenancy: weaviate.configure.multiTenancy({    enabled: true,    autoTenantCreation: true  })})
Go
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)
  }
}
Java
client.collections.create("CollectionWithAutoMTEnabled",
    col -> col.multiTenancy(mt -> mt.autoTenantCreation(true)));
C#
await client.Collections.Create(
    new CollectionCreateParams
    {
        Name = "CollectionWithAutoMTEnabled",
        MultiTenancyConfig = new MultiTenancyConfig
        {
            Enabled = true,
            AutoTenantCreation = true,
        },
    }
);
cURL
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  }}'

Use the client to update the auto-tenant creation setting. Auto-tenant is only available for batch inserts.

Python
from weaviate.classes.config import Reconfigurecollection = client.collections.use(collection_name)collection.config.update(    multi_tenancy_config=Reconfigure.multi_tenancy(auto_tenant_creation=True))
JavaScript/TypeScript
import { reconfigure } from 'weaviate-client';
Go
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)
}
Java
CollectionHandle<Map<String, Object>> collection =
    client.collections.use(collectionName);
collection.config
    .update(col -> col.multiTenancy(mt -> mt.autoTenantCreation(true)));
C#
var collection = client.Collections.Use(collectionName);
await collection.Config.Update(c =>
{
    c.MultiTenancyConfig.AutoTenantCreation = true;
});

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.

Python
from weaviate.classes.tenants import Tenant# Add two tenants to the collectionmulti_collection.tenants.create(    tenants=[        Tenant(name="tenantA"),        Tenant(name="tenantB"),    ])
JavaScript/TypeScript
const multiCollection = client.collections.use(collectionName);await multiCollection.tenants.create([  { name: 'tenantA' },  { name: 'tenantB' }])
Go
client.Schema().TenantsCreator().  WithClassName("MultiTenancyCollection").  WithTenants(models.Tenant{Name: "tenantA"}, models.Tenant{Name: "tenantB"}).  Do(ctx)
Java
collection.tenants.create(Tenant.active("tenantA"),
    Tenant.active("tenantB"));
C#
await collection.Tenants.Create(["tenantA", "tenantB"]);

List existing tenants in a collection.

This example lists the tenants in the MultiTenancyCollection collection:

Python
multi_collection = client.collections.use("MultiTenancyCollection")tenants = multi_collection.tenants.get()print(tenants)
JavaScript/TypeScript
const multiCollection = client.collections.use(collectionName);let tenants = await multiCollection.tenants.get()console.log(tenants)
Go
tenants, err := client.Schema().TenantsGetter().
  WithClassName("MultiTenancyCollection").
  Do(ctx)
Java
List<Tenant> tenants = collection.tenants.get();
System.out.println(tenants);
C#
var tenants = await collection.Tenants.List();
foreach (var t in tenants)
    Console.WriteLine(t.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:

Python
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)
JavaScript/TypeScript
const multiCollection = client.collections.use(collectionName);const tenants = await multiCollection.tenants.getByNames(['tenantA', 'tenantB'])console.log(tenants)
Java
List<String> tenantNames =
    Arrays.asList("tenantA", "tenantB", "nonExistentTenant");
List<Tenant> tenants = collection.tenants.get(tenantNames);
System.out.println(tenants);
C#
var tenantNames = new[] { "tenantA", "tenantB", "nonExistentTenant" };
var tenants = await collection.Tenants.List(tenantNames);
foreach (var t in tenants)
    Console.WriteLine(t.Name);

Get a particular tenant from a collection.

This example returns a tenant from the MultiTenancyCollection collection:

Python
multi_collection = client.collections.use("MultiTenancyCollection")tenant_obj = multi_collection.tenants.get_by_name(tenant_name)print(tenant_obj.name)
JavaScript/TypeScript
const multiCollection = client.collections.use(collectionName);const tenant = await multiCollection.tenants.getByName('tenantA')console.log(tenant)
Java
String tenantName = "tenantA";
Optional<Tenant> tenant = collection.tenants.get(tenantName);
System.out.println(tenant);
C#
string tenantName = "tenantA";
var tenant = await collection.Tenants.Get(tenantName);
Console.WriteLine(tenant?.Name);

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.

Python
multi_collection = client.collections.use("MultiTenancyCollection")# Remove a list of tenants - tenantX will be ignored.multi_collection.tenants.remove(["tenantB", "tenantX"])
JavaScript/TypeScript
const multiCollection = client.collections.use(collectionName);await multiCollection.tenants.remove([  { name: 'tenantB' },  { name: 'tenantX' }  // tenantX will be ignored])
Go
client.Schema().TenantsDeleter().
  WithClassName("MultiTenancyCollection").
  WithTenants("tenantB", "tenantX"). // tenantX will be ignored
  Do(ctx)
Java
collection.tenants.delete(Arrays.asList("tenantB", "tenantX"));
C#
await collection.Tenants.Delete(new[] { "tenantB", "tenantX" });

Change a tenant state between ACTIVE, INACTIVE, and OFFLOADED.

Python
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    )])
JavaScript/TypeScript
const multiCollection = client.collections.use(collectionName)await multiCollection.tenants.update({  name: 'tenantA',  activityStatus: 'ACTIVE' // 'INACTIVE', 'OFFLOADED'})
Java
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 module
C#
string 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 configuration

Multi-tenancy collections require tenant name (e.g. tenantA) with each CRUD operation, as shown in the object creation example below.

Python
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"    })
JavaScript/TypeScript
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'})
Go
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)
Java
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 UUID
C#
var 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 UUID

Multi-tenancy collections require the tenant name (e.g. tenantA) with each Get and Aggregate query operation.

Python
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)
JavaScript/TypeScript
const multiCollection = client.collections.use(collectionName);const multiTenantA = multiCollection.withTenant('tenantA')const objectA = await multiTenantA.query.fetchObjects({  limit: 2})console.log(objectA.objects)
Go
result, err := client.GraphQL().Get().  WithClassName("MultiTenancyCollection").  WithFields(graphql.Field{Name: "question"}).  WithTenant("tenantA").  Do(ctx)
Java
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());}
C#
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));}

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.

Python
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)
JavaScript/TypeScript
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})
Go
// 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)
Java
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
);
C#
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);

Have a question or feedback? Here's how to reach us.

Suggest an edit

Propose a replacement for this page. The site team reviews it before applying any changes.

Export
Documentation menu