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 availability
- Multi-tenancy added in
v1.20
- (Experimental) Tenant activity status setting added in
v1.21
Enable multi-tenancy
Multi-tenancy is disabled by default. To enable multi-tenancy, set multiTenancyConfig
in the collection definition:
- Python Client v4
- Python Client v3
- JS/TS Client v3
- JS/TS Client v2
- Java
- Go
from weaviate.classes.config import Configure
multi_collection = client.collections.create(
name="MultiTenancyCollection",
# Enable multi-tenancy on the new collection
multi_tenancy_config=Configure.multi_tenancy(enabled=True)
)
client.schema.create_class({
"class": "MultiTenancyCollection",
"multiTenancyConfig": {"enabled": True}
})
const result = await client.collections.create({
name: 'MultiTenancyCollection',
multiTenancy: weaviate.configure.multiTenancy({enabled: true})
}
)
await client.schema
.classCreator().withClass({
class: 'MultiTenancyCollection',
multiTenancyConfig: { enabled: true },
})
.do();
WeaviateClass multiTenancyCollection = WeaviateClass.builder()
.className("MultiTenancyCollection")
.multiTenancyConfig(MultiTenancyConfig.builder().enabled(true).build())
.build();
client.schema().classCreator()
.withClass(multiTenancyCollection)
.run();
client.Schema().ClassCreator().
WithClass(&models.Class{
Class: "MultiTenancyCollection",
MultiTenancyConfig: &models.MultiTenancyConfig{
Enabled: true,
},
}).
Do(ctx)
Automatically add new tenants
By default, Weaviate returns an error if you try to insert an object into a non-existent tenant. To create a new tenant instead, set autoTenantCreation
to true
in the collection definition. The auto-tenant feature is only available during batch imports.
Set autoTenantCreation
when you create the collection, or update the setting as needed.
Automatic tenant creation is useful when you batch 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
- Python (v4)
- cURL
from weaviate.classes.config import Configure
multi_collection = client.collections.create(
name="CollectionWithAutoMTEnabled",
# Enable automatic tenant creation
multi_tenancy_config=Configure.multi_tenancy(
enabled=True,
auto_tenant_creation=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
Use the client to update the auto-tenant creation setting. Auto-tenant is only available for batch inserts.
- Python (v4)
from weaviate.collections.classes.config import Reconfigure
collection = client.collections.get(collection_name)
collection.config.update(
multi_tenancy_config=Reconfigure.multi_tenancy(auto_tenant_creation=True)
)
Add new tenants manually
To add tenants to a collection, specify the collection and the new tenants. Optionally, specify the tenant activity status as HOT
(active, default) or COLD
(inactive).
This example adds tenantA
to the MultiTenancyCollection
collection:
Additional information
Tenant status is available from Weaviate 1.21
onwards.
A tenant name can only contain alphanumeric characters (a-z, A-Z, 0-9), underscore (_), and hyphen (-), with a length of 4 to 64 characters.
- Python Client v4
- Python Client v3
- JS/TS Client v3
- JS/TS Client v2
- Java
- Go
from weaviate.classes.tenants import Tenant
# Add two tenants to the collection
multi_collection.tenants.create(
tenants=[
Tenant(name="tenantA"),
Tenant(name="tenantB"),
]
)
from weaviate import Tenant
client.schema.add_class_tenants(
class_name="MultiTenancyCollection", # The class to which the tenants will be added
tenants=[Tenant(name="tenantA"), Tenant(name="tenantB")]
)
const multiCollection = client.collections.get('MultiTenancyCollection');
await multiCollection.tenants.create([
{ name: 'tenantA'},
{ name: 'tenantB'}
])
let tenants = await client.schema
.tenantsCreator(
'MultiTenancyCollection',
[{ name: 'tenantA' }, { name: 'tenantB' }]
)
.do();
client.schema().tenantsCreator()
.withClassName("MultiTenancyCollection")
.withTenants(
Tenant.builder().name("tenantA").build(),
Tenant.builder().name("tenantB").build()
)
.run();
client.Schema().TenantsCreator().
WithClassName("MultiTenancyCollection").
WithTenants(models.Tenant{Name: "tenantA"}, models.Tenant{Name: "tenantB"}).
Do(ctx)
List all tenants
List existing tenants in a collection.
This example lists the tenants in the MultiTenancyCollection
collection:
- Python Client v4
- Python Client v3
- JS/TS Client v3
- JS/TS Client v2
- Java
- Go
multi_collection = client.collections.get("MultiTenancyCollection")
tenants = multi_collection.tenants.get()
print(tenants)
tenants = client.schema.get_class_tenants(
class_name="MultiTenancyCollection" # The class from which the tenants will be retrieved
)
const multiCollection = client.collections.get('MultiTenancyCollection');
const tenants = await multiCollection.tenants.get()
console.log(tenants)
tenants = await client.schema
.tenantsGetter('MultiTenancyCollection')
.do();
client.schema().tenantsGetter()
.withClassName("MultiTenancyCollection")
.run();
tenants, err := client.Schema().TenantsGetter().
WithClassName("MultiTenancyCollection").
Do(ctx)
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:
- Python (v4)
- JS/TS v3
multi_collection = client.collections.get("MultiTenancyCollection")
tenant_names = ["tenantA", "tenantB", "nonExistentTenant"] # `nonExistentTenant`` does not exist and will be ignored
tenants_response = multi_collection.tenants.get_by_names(tenant_names)
for k, v in tenants_response.items():
print(k, v)
// Coming soon
Get one tenant
Get a particular tenant from a collection.
This example returns a tenant from the MultiTenancyCollection
collection:
- Python (v4)
- JS/TS v3
multi_collection = client.collections.get("MultiTenancyCollection")
tenant_obj = multi_collection.tenants.get_by_name(tenant_name)
print(tenant_obj.name)
// Coming soon
Delete tenants
To delete tenants from a collection, specify the collection and the tenants. The delete operation ignores tenant names if the named tenant is not a part of the collection.
In this example, Weaviate removes tenantB
and tenantX
from the MultiTenancyCollection
collection.
- Python Client v4
- Python Client v3
- JS/TS Client v3
- JS/TS Client v2
- Java
- Go
multi_collection = client.collections.get("MultiTenancyCollection")
# Remove a list of tenants - tenantX will be ignored.
multi_collection.tenants.remove(["tenantB", "tenantX"])
client.schema.remove_class_tenants(
class_name="MultiTenancyCollection", # The class from which the tenants will be removed
tenants=["tenantB", "tenantX"] # The tenants to be removed. tenantX will be ignored.
)
const multiCollection = client.collections.get('MultiTenancyCollection');
await multiCollection.tenants.remove([
{ name: 'tenantB'},
{ name: 'tenantX'} // tenantX will be ignored
])
await client.schema
.tenantsDeleter('MultiTenancyCollection', ['tenantB', 'tenantX']) // tenantX will be ignored
.do();
client.schema().tenantsDeleter()
.withClassName("MultiTenancyCollection")
.withTenants("tenantB", "tenantX") // tenantX will be ignored
.run();
client.Schema().TenantsDeleter().
WithClassName("MultiTenancyCollection").
WithTenants("tenantB", "tenantX"). // tenantX will be ignored
Do(ctx)
Update tenant activity status
Update existing tenants' activity status to active (HOT
) or inactive (COLD
).
- Python Client v4
from weaviate.classes.tenants import Tenant
multi_collection = client.collections.get("MultiTenancyCollection")
multi_collection.tenants.update(tenants=[
Tenant(
name="tenantA",
activity_status=weaviate.schema.TenantActivityStatus.COLD
)
])
Additional information
- This feature was added in
v1.21
- Other client code examples coming soon
- For now, please send a PUT request through the REST API endpoint to update the tenant activity status.
CRUD operations
Multi-tenancy collections require tenant name (e.g. tenantA
) with each CRUD operation, as shown in the object creation example below.
- Python Client v4
- Python Client v3
- JS/TS Client v3
- JS/TS Client v2
- Java
- Go
multi_collection = client.collections.get("MultiTenancyCollection")
# Get collection specific to the required tenant
multi_tenantA = multi_collection.with_tenant("tenantA")
# Insert an object to tenantA
object_id = multi_tenantA.data.insert(
properties={
"question": "This vector DB is OSS & supports automatic property type inference on import"
}
)
object_id = client.data_object.create(
class_name="MultiTenancyCollection", # The class to which the object will be added
data_object={
"question": "This vector DB is OSS & supports automatic property type inference on import"
},
tenant="tenantA" # The tenant to which the object will be added
)
const multiCollection = client.collections.get('MultiTenancyCollection');
const multiTenantA = multiCollection.withTenant('tenantA')
await multiTenantA.data.insert({
question: 'This vector DB is OSS & supports automatic property type inference on import'
})
let object = await client.data.creator()
.withClassName('MultiTenancyCollection') // The class to which the object will be added
.withProperties({
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();
Result<WeaviateObject> result = client.data().creator()
.withClassName("MultiTenancyCollection") // The class to which the object will be added
.withProperties(new HashMap<String, Object>() {{
put("question", "This vector DB is OSS & supports automatic property type inference on import");
}})
.withTenant("tenantA") // The tenant to which the object will be added
.run();
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)
Search queries
Multi-tenancy collections require the tenant name (e.g. tenantA
) with each Get
and Aggregate
query operation.
- Python Client v4
- Python Client v3
- JS/TS Client v3
- JS/TS Client v2
- Java
- Go
multi_collection = client.collections.get("MultiTenancyCollection")
# Get collection specific to the required tenant
multi_tenantA = multi_collection.with_tenant("tenantA")
# Query tenantA
result = multi_tenantA.query.fetch_objects(
limit=2,
)
print(result.objects[0].properties)
result = (
client.query.get("MultiTenancyCollection", ["question"])
.with_tenant("tenantA")
.do()
)
const multiCollection = await client.collections.get('MultiTenancyCollection');
const multiTenantA = multiCollection.withTenant('tenantA')
const objectA = await multiTenantA.query.fetchObjects({
limit: 2
})
console.log(objectA.objects)
const result = await client.graphql
.get()
.withClassName('MultiTenancyCollection')
.withFields('question')
.withTenant('tenantA')
.do();
Result<GraphQLResponse> result = client.graphQL().get()
.withClassName("MultiTenancyCollection")
.withFields(Field.builder().name("question").build())
.withTenant("tenantA")
.run();
result, err := client.GraphQL().Get().
WithClassName("MultiTenancyCollection").
WithFields(graphql.Field{Name: "question"}).
WithTenant("tenantA").
Do(ctx)
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.
- Python Client v4
- Python Client v3
- JS/TS Client v3
- JS/TS Client v2
- Java
- Go
from weaviate.classes.config import ReferenceProperty
multi_collection = client.collections.get("MultiTenancyCollection")
# Add the cross-reference property to the multi-tenancy class
multi_collection.config.add_reference(
ReferenceProperty(
name="hasCategory",
target_collection="JeopardyCategory"
)
)
# Get collection specific to the required tenant
multi_tenantA = multi_collection.with_tenant(tenant="tenantA")
# Add reference from MultiTenancyCollection object to a JeopardyCategory object
multi_tenantA.data.reference_add(
from_uuid=object_id, # MultiTenancyCollection object id (a Jeopardy question)
from_property="hasCategory",
to=category_id # JeopardyCategory id
)
# Add the cross-reference property to the multi-tenancy class
client.schema.property.create("MultiTenancyCollection", {
"name": "hasCategory",
"dataType": ["JeopardyCategory"],
})
client.data_object.reference.add(
from_uuid=object_id, # MultiTenancyCollection object id (a Jeopardy question)
from_class_name="MultiTenancyCollection",
from_property_name="hasCategory",
tenant="tenantA",
to_class_name="JeopardyCategory",
to_uuid=category_id
)
// Add the cross-reference property to the multi-tenancy class
const multiCollection = await client.collections.get('MultiTenancyCollection');
const categoryId = '...'
const objectId = '...'
await 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 class
await client.schema.propertyCreator()
.withClassName('MultiTenancyCollection')
.withProperty({
'name': 'hasCategory',
'dataType': ['JeopardyCategory'],
})
.do();
// Create the cross-reference from MultiTenancyCollection object to the JeopardyCategory object
await client.data
.referenceCreator()
.withClassName('MultiTenancyCollection')
.withTenant('tenantA')
.withId(object.id) // MultiTenancyCollection object id (a Jeopardy question)
.withReferenceProperty('hasCategory')
.withReference(
client.data
.referencePayloadBuilder()
.withClassName('JeopardyCategory')
.withId(category.id)
.payload()
)
.do();
// Add the cross-reference property to the multi-tenancy class
client.schema().propertyCreator()
.withClassName("MultiTenancyCollection")
.withProperty(Property.builder()
.name("hasCategory")
.dataType(Collections.singletonList("JeopardyCategory")).build()
)
.run();
// Create the cross-reference from MultiTenancyCollection object to the JeopardyCategory object
client.data().referenceCreator()
.withClassName("MultiTenancyCollection")
.withTenant("tenantA")
.withID(object.getId()) // MultiTenancyCollection object id (a Jeopardy question)
.withReferenceProperty("hasCategory")
.withReference(
client.data()
.referencePayloadBuilder()
.withClassName("JeopardyCategory")
.withID(category.getId())
.payload()
)
.run();
// Add the cross-reference property to the multi-tenancy class
client.Schema().PropertyCreator().
WithClassName("MultiTenancyCollection").
WithProperty(&models.Property{
Name: "hasCategory",
DataType: []string{"JeopardyCategory"},
}).
Do(ctx)
// Create the cross-reference from MultiTenancyCollection object to the JeopardyCategory object
client.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)
Related pages
- Connect to Weaviate
- How to: Configure a schema
- References: REST API: Schema
- Concepts: Data Structure: Multi-tenancy
Questions and feedback
If you have any questions or feedback, let us know in the user forum.