Skip to main content
Go to documentation:
⌘U
Weaviate Database

Develop AI applications using Weaviate's APIs and tools

Deploy

Deploy, configure, and maintain Weaviate Database

Query Agent

Run agentic search over your Weaviate Cloud collections

Weaviate Cloud

Manage and scale Weaviate in the cloud

Engram

Persistent memory for LLM agents and applications

Additional resources

Integrations
Weaviate Academy

Need help?

Weaviate LogoAsk AI Assistant⌘K
Support
Community Forum
Contributor guide

Batch import

Batch imports are an efficient way to add multiple data objects and cross-references. For most use cases, we recommend server-side batching as the starting point: the server tells the client how much data to send next, so you don't have to tune batch parameters yourself. When you need manual control over the batch size and concurrency, or you are using a client that does not yet support server-side batching, use manual batching instead.

Server-side batching

Added in v1.36

With server-side batch imports (also called "automatic" batching), the client sends data in batch sizes determined by feedback from the server. This simplifies your code and helps the server manage its own load. Server-side batching offers two entry points:

  • Stream from a data source (recommended for large datasets): Add objects to the import one at a time as you read them from the source, so the full dataset never has to fit in memory.
  • Ingest an in-memory list: Import a list of objects that you already hold in memory with a single call.

Server-side batching uses the gRPC API, which current client versions enable by default.

The following example adds objects to a collection named MyCollection.

py docs  API docs
More infoCode snippets in the documentation reflect the latest client library and Weaviate Database version. Check the Release notes for specific versions.

If a snippet doesn't work or you have feedback, please open a GitHub issue.

Open the batch.stream() context manager and add objects one at a time; the client sends them at the pace the server requests. The async Python client also supports server-side batching through the stream() method and the one-shot ingest() method.

data_rows = [
{"title": f"Object {i+1}"} for i in range(5)
]

collection = client.collections.use("MyCollection")

# Use `stream` for server-side batching. The client will send data
# in batches at a rate specified by the server.
with collection.batch.stream() as batch:
for data_row in data_rows:
batch.add_object(
properties=data_row,
)
if batch.number_errors > 10:
print("Batch import stopped due to excessive errors.")
break

failed_objects = collection.batch.failed_objects
if failed_objects:
print(f"Number of failed imports: {len(failed_objects)}")
print(f"First failed object: {failed_objects[0]}")

You can also stream from a data source with data.ingest(). It accepts any iterable, so you can pass a generator that reads a source file record by record. Objects go to the server as the generator produces them, so the source never has to fit in memory. To import objects that you already hold in a list, see Ingest an in-memory list.

import json

# Each line of the source file holds one JSON object
def read_objects(path):
with open(path) as f:
for line in f:
line = line.strip()
if not line: # Skip blank lines
continue
record = json.loads(line)
yield {"title": record["title"]}

collection = client.collections.use("MyCollection")

# `ingest` pulls objects from the generator as it goes
result = collection.data.ingest(read_objects("my-data.jsonl"))

if result.errors:
print(f"Number of failed imports: {len(result.errors)}")

Ingest an in-memory list

If your objects are already in memory, you can import the whole list with a single call. The client sends the list using server-side batching, so the import is safe for large lists that would exceed the server's GRPC_MAX_MESSAGE_SIZE limit if sent as one request.

py docs  API docs
More infoCode snippets in the documentation reflect the latest client library and Weaviate Database version. Check the Release notes for specific versions.

If a snippet doesn't work or you have feedback, please open a GitHub issue.

data.ingest() is the safe replacement for passing a large list to insert_many, which sends all objects in a single request. ingest accepts plain property dicts or DataObject instances (to set object IDs, vectors, or references) and returns the same return object as insert_many.

data_rows = [
{"title": f"Object {i+1}"} for i in range(5)
]

collection = client.collections.use("MyCollection")

# `ingest` imports the whole list with server-side batching in a single call
result = collection.data.ingest(data_rows)

# The return object is the same as for `insert_many`
if result.errors:
print(f"Number of failed imports: {len(result.errors)}")
# `errors` is a dict keyed by the index of the failed object
for index, error in result.errors.items():
print(f"Failed object at index {index}: {error.message}")

Manual batching

Use manual (client-side) batching when you want to control the batch size and concurrency yourself, or when using a client that does not yet support server-side batching (such as the Go client). The following example adds objects to the MyCollection collection.

py docs  API docs
More infoCode snippets in the documentation reflect the latest client library and Weaviate Database version. Check the Release notes for specific versions.

If a snippet doesn't work or you have feedback, please open a GitHub issue.
data_rows = [
{"title": f"Object {i+1}"} for i in range(5)
]

collection = client.collections.use("MyCollection")

with collection.batch.fixed_size(batch_size=200) as batch:
for data_row in data_rows:
batch.add_object(
properties=data_row,
)
if batch.number_errors > 10:
print("Batch import stopped due to excessive errors.")
break

failed_objects = collection.batch.failed_objects
if failed_objects:
print(f"Number of failed imports: {len(failed_objects)}")
print(f"First failed object: {failed_objects[0]}")

Error handling

Batch imports report failures per object: a problem with one object does not abort the rest of the import. Errors are reported the same way in server-side and manual batching. Inspect the failed items during and after the import to catch data issues early.

py docs  API docs
More infoCode snippets in the documentation reflect the latest client library and Weaviate Database version. Check the Release notes for specific versions.

If a snippet doesn't work or you have feedback, please open a GitHub issue.
  • Within a batching context manager, batch.number_errors holds a running count of failed objects and references. You can use this counter to stop the import process and investigate the failures.
  • After the context closes, collection.batch.failed_objects and collection.batch.failed_references contain the failed items.
  • The one-shot data.ingest() method returns the same result object as insert_many: its errors dict maps the original index of each failed object to its error.

Find out more about error handling on the Python client reference page.

Customize imported objects

Batch-imported objects support the same parameters as individually created objects, such as custom IDs, vectors, and cross-references. These parameters work the same way in server-side and manual batching.

Specify an ID value

Weaviate generates an UUID for each object. Object IDs must be unique. If you set object IDs, use one of these deterministic UUID methods to prevent duplicate IDs:

  • generate_uuid5 (Python)
  • generateUuid5 (TypeScript)
py docs  API docs
More infoCode snippets in the documentation reflect the latest client library and Weaviate Database version. Check the Release notes for specific versions.

If a snippet doesn't work or you have feedback, please open a GitHub issue.
from weaviate.util import generate_uuid5  # Generate a deterministic ID
from weaviate.classes.data import DataObject

data_rows = [{"title": f"Object {i+1}"} for i in range(5)]

collection = client.collections.use("MyCollection")

data_objects = [
DataObject(
properties=data_row,
uuid=generate_uuid5(data_row)
)
for data_row in data_rows
]

result = collection.data.ingest(data_objects)

if result.errors:
print(f"Number of failed imports: {len(result.errors)}")

Specify a vector

Use the vector property to specify a vector for each object.

py docs  API docs
More infoCode snippets in the documentation reflect the latest client library and Weaviate Database version. Check the Release notes for specific versions.

If a snippet doesn't work or you have feedback, please open a GitHub issue.
from weaviate.classes.data import DataObject

data_rows = [{"title": f"Object {i+1}"} for i in range(5)]
vectors = [[0.1] * 1536 for i in range(5)]

collection = client.collections.use("MyCollection")

data_objects = [
DataObject(
properties=data_row,
vector=vectors[i]
)
for i, data_row in enumerate(data_rows)
]

result = collection.data.ingest(data_objects)

if result.errors:
print(f"Number of failed imports: {len(result.errors)}")

Specify named vectors

When you create an object, you can specify named vectors (if configured in your collection).

py docs  API docs
More infoCode snippets in the documentation reflect the latest client library and Weaviate Database version. Check the Release notes for specific versions.

If a snippet doesn't work or you have feedback, please open a GitHub issue.
from weaviate.classes.data import DataObject

data_rows = [{
"title": f"Object {i+1}",
"body": f"Body {i+1}"
} for i in range(5)]

title_vectors = [[0.12] * 1536 for _ in range(5)]
body_vectors = [[0.34] * 1536 for _ in range(5)]

collection = client.collections.use("MyCollection")

data_objects = [
DataObject(
properties=data_row,
vector={
"title": title_vectors[i],
"body": body_vectors[i],
}
)
for i, data_row in enumerate(data_rows)
]

result = collection.data.ingest(data_objects)

if result.errors:
print(f"Number of failed imports: {len(result.errors)}")

Import with references

You can batch create links from an object to another object through cross-references.

py docs  API docs
More infoCode snippets in the documentation reflect the latest client library and Weaviate Database version. Check the Release notes for specific versions.

If a snippet doesn't work or you have feedback, please open a GitHub issue.
from weaviate.classes.data import DataObject

collection = client.collections.use("Author")

data_objects = [
DataObject(
properties={"name": "Jane Austen"},
references={"writesFor": target_uuid},
),
]

result = collection.data.ingest(data_objects)

if result.errors:
print(f"Number of failed imports: {len(result.errors)}")

Stream data from large files

If your dataset does not fit in memory, do not load it all at once. Instead, read the source file lazily and add objects to the import as you go:

  • With the server-side streaming context, add each object as you read it from the file. The client sends data at the pace the server requests, so memory usage stays flat.
  • In Python and TypeScript, the one-shot import method accepts any iterable, so you can pass a lazy source, such as a generator that reads the file record by record, instead of a fully loaded list.
  • With manual batching, apply the same pattern: add objects to the batch as you read them.

For JSON files, use a streaming parser that yields one object at a time (such as ijson in Python). For CSV files, read the file in chunks (such as pandas with the chunksize parameter) rather than loading it whole.

Batch vectorization

Some model providers provide batch vectorization APIs, where each request can include multiple objects.

From Weaviate v1.25.0, a batch import automatically makes use of the model providers' batch vectorization APIs where available. This reduces the number of requests to the model provider, improving throughput.

Model provider configurations

You can configure the batch vectorization settings for each model provider, such as the requests per minute or tokens per minute. The following examples sets rate limits for Cohere and OpenAI integrations, and provides API keys for both.

Note that each provider exposes different configuration options.

py docs  API docs
More infoCode snippets in the documentation reflect the latest client library and Weaviate Database version. Check the Release notes for specific versions.

If a snippet doesn't work or you have feedback, please open a GitHub issue.
from weaviate.classes.config import Integrations

integrations = [
# Each model provider may expose different parameters
Integrations.cohere(
api_key=cohere_key,
requests_per_minute_embeddings=rpm_embeddings,
),
Integrations.openai(
api_key=openai_key,
requests_per_minute_embeddings=rpm_embeddings,
tokens_per_minute_embeddings=tpm_embeddings, # e.g. OpenAI also exposes tokens per minute for embeddings
),
]
client.integrations.configure(integrations)

Additional considerations

Data imports can be resource intensive. Consider the following when you import large amounts of data.

Asynchronous imports

To maximize import speed, enable asynchronous indexing by setting the ASYNC_INDEXING environment variable to true in your Weaviate configuration. This decouples vector index construction from object creation, so imports are not slowed down by index building.

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.

For details, see auto-tenant.

Further resources

Questions and feedback