# Migrate data

Follow these examples to migrate data manually when using a backup is not possible. They cover all permutations between:

- a single-tenancy collection (Collection), and
- a tenant in a multi-tenancy collection (Tenant).

:::accordion{title="Additional information"}
The examples use two different Weaviate instances, exposed through different ports. The same process can be used for two different instances as well.

Cross-references in Weaviate are properties. As such, you can [retrieve cross-reference](cross-references.md#read-cross-references) as a part of the object.
:::

:::accordion{title="What about cross-references?"}
These scripts should migrate cross-references as well.

Cross-references are properties. As such, these cursor-based exports will include them.
During restoration, restore the cross-referenced (i.e. "to") object first, then the object that contains the cross-reference (i.e. "from" object).
:::

## Collection → Collection

#### Step 1: Create the target collection(s)

Create a collection (e.g. `WineReview`) at the target instance, matching the collection (e.g. `WineReview`) at the source instance.

:::code-group{sync="languages"}
```python title="Python"
import weaviate
import weaviate.classes as wvc
from weaviate.collections import Collection
from weaviate.client import WeaviateClient
```

```typescript title="JavaScript/TypeScript"
import weaviate, { Collection, WeaviateClient } from 'weaviate-client'

let client_src: WeaviateClient,client_tgt: WeaviateClient;
let reviews_mt_tgt, reviews_mt_src;
```

```javaraw title="Java"
private static CollectionHandle<Map<String, Object>> createCollection(
    WeaviateClient clientIn, String collectionName, boolean enableMt)
    throws IOException {
```

```csharpraw title="C#"
private static async Task<CollectionClient> CreateCollection(
    WeaviateClient clientIn,
    string collectionName,
    bool enableMt
)
{
```
:::

#### Step 2: Migrate the data

Migrate:

- The `source collection` data in the `client_src` instance
- to `target collection` in the `client_tgt` instance

:::code-group{sync="languages"}
```python title="Python"
def migrate_data(collection_src: Collection, collection_tgt: Collection):
```

```typescript title="JavaScript/TypeScript"
let reviews_tgt, reviews_src;
```

```javaraw title="Java"
private void migrateData(CollectionHandle<Map<String, Object>> collectionSrc,
    CollectionHandle<Map<String, Object>> collectionTgt) {
  System.out.println("Starting data migration...");
  List<WeaviateObject<Map<String, Object>>> sourceObjects = StreamSupport
      .stream(collectionSrc.paginate(p -> p.includeVector()).spliterator(),
          false)
      .map(readObj -> WeaviateObject
          .<Map<String, Object>>of(c -> c.properties(readObj.properties())
              .uuid(readObj.uuid())
              .vectors(readObj.vectors())))
      .collect(Collectors.toList());

  collectionTgt.data.insertMany(sourceObjects);

  System.out.println("Data migration complete.");
}
```

```csharpraw title="C#"
private async Task MigrateData<T>(
    CollectionClient collectionSrc,
    CollectionClient collectionTgt
)
{
    Console.WriteLine("Starting data migration...");

    // Fetch source objects
    var response = await collectionSrc.Query.FetchObjects(limit: 10000, includeVectors: true);

    // Map to Strong Type List
    var sourceObjects = new List<T>();
    foreach (var obj in response.Objects)
    {
        // Deserialize the inner properties Dictionary to the POCO type
        var json = JsonSerializer.Serialize(obj.Properties);
        var typedObj = JsonSerializer.Deserialize<T>(json);
        if (typedObj != null)
        {
            sourceObjects.Add(typedObj);
        }
    }

    // InsertMany using Strong Types
    await collectionTgt.Data.InsertMany(sourceObjects.ToArray());

    Console.WriteLine($"Data migration complete. Migrated {sourceObjects.Count} objects.");
}
```
:::

## Collection → Tenant

#### Step 1: Create the target collection(s)

Create a collection (e.g. `WineReview`) at the target instance, matching the collection (e.g. `WineReview`) at the source instance, and enable multi-tenancy for the target collection.

:::code-group{sync="languages"}
```python title="Python"
import weaviate
import weaviate.classes as wvc
from weaviate.collections import Collection
from weaviate.client import WeaviateClient
```

```typescript title="JavaScript/TypeScript"
import weaviate, { Collection, WeaviateClient } from 'weaviate-client'

let client_src: WeaviateClient,client_tgt: WeaviateClient;
let reviews_mt_tgt, reviews_mt_src;
```

```javaraw title="Java"
private static CollectionHandle<Map<String, Object>> createCollection(
    WeaviateClient clientIn, String collectionName, boolean enableMt)
    throws IOException {
```

```csharpraw title="C#"
private static async Task<CollectionClient> CreateCollection(
    WeaviateClient clientIn,
    string collectionName,
    bool enableMt
)
{
```
:::

#### Step 2: Create the tenant(s)

Add tenants at the target instance before adding data objects.

:::code-group{sync="languages"}
```python title="Python"
tenants_tgt = [wvc.tenants.Tenant(name="tenantA"), wvc.tenants.Tenant(name="tenantB")]

reviews_mt_tgt = client_tgt.collections.get("WineReviewMT")
reviews_mt_tgt.tenants.create(tenants_tgt)
```

```typescript title="JavaScript/TypeScript"
let tenantsTgt = [
    { name: 'tenantA'},
    { name: 'tenantB'}
  ]

reviews_mt_tgt = client_tgt.collections.use("WineReviewMT")
reviews_mt_tgt.tenants.create(tenantsTgt)
```

```javaraw title="Java"
void createTenants() throws IOException {
  var reviewsMtTgt = clientTgt.collections.use("WineReviewMT");

  var tenantsTgt =
      List.of(Tenant.active("tenantA"), Tenant.active("tenantB"));
  reviewsMtTgt.tenants.create(tenantsTgt);
}
```

```csharpraw title="C#"
private async Task CreateTenants()
{
    var reviewsMtTgt = clientTgt.Collections.Use("WineReviewMT");

    var tenantsTgt = new[]
    {
        new Tenant { Name = "tenantA" },
        new Tenant { Name = "tenantB" },
    };
    await reviewsMtTgt.Tenants.Create(tenantsTgt);
}
```
:::

#### Step 3: Migrate the data

Migrate:

- The `source collection` data in the `client_src` instance
- to `target tenant` data from `target collection` in the `client_tgt` instance

:::code-group{sync="languages"}
```python title="Python"
def migrate_data(collection_src: Collection, collection_tgt: Collection):
```

```typescript title="JavaScript/TypeScript"
let reviews_tgt, reviews_src;
```

```javaraw title="Java"
private void migrateData(CollectionHandle<Map<String, Object>> collectionSrc,
    CollectionHandle<Map<String, Object>> collectionTgt) {
  System.out.println("Starting data migration...");
  List<WeaviateObject<Map<String, Object>>> sourceObjects = StreamSupport
      .stream(collectionSrc.paginate(p -> p.includeVector()).spliterator(),
          false)
      .map(readObj -> WeaviateObject
          .<Map<String, Object>>of(c -> c.properties(readObj.properties())
              .uuid(readObj.uuid())
              .vectors(readObj.vectors())))
      .collect(Collectors.toList());

  collectionTgt.data.insertMany(sourceObjects);

  System.out.println("Data migration complete.");
}
```

```csharpraw title="C#"
private async Task MigrateData<T>(
    CollectionClient collectionSrc,
    CollectionClient collectionTgt
)
{
    Console.WriteLine("Starting data migration...");

    // Fetch source objects
    var response = await collectionSrc.Query.FetchObjects(limit: 10000, includeVectors: true);

    // Map to Strong Type List
    var sourceObjects = new List<T>();
    foreach (var obj in response.Objects)
    {
        // Deserialize the inner properties Dictionary to the POCO type
        var json = JsonSerializer.Serialize(obj.Properties);
        var typedObj = JsonSerializer.Deserialize<T>(json);
        if (typedObj != null)
        {
            sourceObjects.Add(typedObj);
        }
    }

    // InsertMany using Strong Types
    await collectionTgt.Data.InsertMany(sourceObjects.ToArray());

    Console.WriteLine($"Data migration complete. Migrated {sourceObjects.Count} objects.");
}
```
:::

## Tenant → Collection

#### Step 1: Create the target collection(s)

Create a collection (e.g. `WineReview`) at the target instance, matching the collection (e.g. `WineReview`) at the source instance, and enable multi-tenancy for the target collection.

:::code-group{sync="languages"}
```python title="Python"
import weaviate
import weaviate.classes as wvc
from weaviate.collections import Collection
from weaviate.client import WeaviateClient
```

```typescript title="JavaScript/TypeScript"
import weaviate, { Collection, WeaviateClient } from 'weaviate-client'

let client_src: WeaviateClient,client_tgt: WeaviateClient;
let reviews_mt_tgt, reviews_mt_src;
```

```javaraw title="Java"
private static CollectionHandle<Map<String, Object>> createCollection(
    WeaviateClient clientIn, String collectionName, boolean enableMt)
    throws IOException {
```

```csharpraw title="C#"
private static async Task<CollectionClient> CreateCollection(
    WeaviateClient clientIn,
    string collectionName,
    bool enableMt
)
{
```
:::

#### Step 2: Migrate the data

Migrate:

- The `source tenant` data from `source collection` in the `client_src` instance
- to `target collection` in the `client_tgt` instance

:::code-group{sync="languages"}
```python title="Python"
def migrate_data(collection_src: Collection, collection_tgt: Collection):
```

```typescript title="JavaScript/TypeScript"
let reviews_tgt, reviews_src;
```

```javaraw title="Java"
private void migrateData(CollectionHandle<Map<String, Object>> collectionSrc,
    CollectionHandle<Map<String, Object>> collectionTgt) {
  System.out.println("Starting data migration...");
  List<WeaviateObject<Map<String, Object>>> sourceObjects = StreamSupport
      .stream(collectionSrc.paginate(p -> p.includeVector()).spliterator(),
          false)
      .map(readObj -> WeaviateObject
          .<Map<String, Object>>of(c -> c.properties(readObj.properties())
              .uuid(readObj.uuid())
              .vectors(readObj.vectors())))
      .collect(Collectors.toList());

  collectionTgt.data.insertMany(sourceObjects);

  System.out.println("Data migration complete.");
}
```

```csharpraw title="C#"
private async Task MigrateData<T>(
    CollectionClient collectionSrc,
    CollectionClient collectionTgt
)
{
    Console.WriteLine("Starting data migration...");

    // Fetch source objects
    var response = await collectionSrc.Query.FetchObjects(limit: 10000, includeVectors: true);

    // Map to Strong Type List
    var sourceObjects = new List<T>();
    foreach (var obj in response.Objects)
    {
        // Deserialize the inner properties Dictionary to the POCO type
        var json = JsonSerializer.Serialize(obj.Properties);
        var typedObj = JsonSerializer.Deserialize<T>(json);
        if (typedObj != null)
        {
            sourceObjects.Add(typedObj);
        }
    }

    // InsertMany using Strong Types
    await collectionTgt.Data.InsertMany(sourceObjects.ToArray());

    Console.WriteLine($"Data migration complete. Migrated {sourceObjects.Count} objects.");
}
```
:::

## Tenant → Tenant

#### Step 1: Create the target collection(s)

Create a collection (e.g. `WineReview`) at the target instance, matching the collection (e.g. `WineReview`) at the source instance including enabling multi-tenancy.

:::code-group{sync="languages"}
```python title="Python"
import weaviate
import weaviate.classes as wvc
from weaviate.collections import Collection
from weaviate.client import WeaviateClient
```

```typescript title="JavaScript/TypeScript"
import weaviate, { Collection, WeaviateClient } from 'weaviate-client'

let client_src: WeaviateClient,client_tgt: WeaviateClient;
let reviews_mt_tgt, reviews_mt_src;
```

```javaraw title="Java"
private static CollectionHandle<Map<String, Object>> createCollection(
    WeaviateClient clientIn, String collectionName, boolean enableMt)
    throws IOException {
```

```csharpraw title="C#"
private static async Task<CollectionClient> CreateCollection(
    WeaviateClient clientIn,
    string collectionName,
    bool enableMt
)
{
```
:::

#### Step 2: Create the tenant(s)

Add tenants at the target instance before adding data objects.

:::code-group{sync="languages"}
```python title="Python"
tenants_tgt = [wvc.tenants.Tenant(name="tenantA"), wvc.tenants.Tenant(name="tenantB")]

reviews_mt_tgt = client_tgt.collections.get("WineReviewMT")
reviews_mt_tgt.tenants.create(tenants_tgt)
```

```typescript title="JavaScript/TypeScript"
let tenantsTgt = [
    { name: 'tenantA'},
    { name: 'tenantB'}
  ]

reviews_mt_tgt = client_tgt.collections.use("WineReviewMT")
reviews_mt_tgt.tenants.create(tenantsTgt)
```

```javaraw title="Java"
void createTenants() throws IOException {
  var reviewsMtTgt = clientTgt.collections.use("WineReviewMT");

  var tenantsTgt =
      List.of(Tenant.active("tenantA"), Tenant.active("tenantB"));
  reviewsMtTgt.tenants.create(tenantsTgt);
}
```

```csharpraw title="C#"
private async Task CreateTenants()
{
    var reviewsMtTgt = clientTgt.Collections.Use("WineReviewMT");

    var tenantsTgt = new[]
    {
        new Tenant { Name = "tenantA" },
        new Tenant { Name = "tenantB" },
    };
    await reviewsMtTgt.Tenants.Create(tenantsTgt);
}
```
:::

#### Step 3: Migrate the data

Migrate:

- The `source tenant` data from `source collection` in the `client_src` instance
- to `target tenant` data from `target collection` in the `client_tgt` instance

:::code-group{sync="languages"}
```python title="Python"
def migrate_data(collection_src: Collection, collection_tgt: Collection):
```

```typescript title="JavaScript/TypeScript"
import weaviate, { Collection, WeaviateClient } from 'weaviate-client'

let client_src: WeaviateClient,client_tgt: WeaviateClient;
let reviews_mt_tgt, reviews_mt_src;
```

```javaraw title="Java"
private void migrateData(CollectionHandle<Map<String, Object>> collectionSrc,
    CollectionHandle<Map<String, Object>> collectionTgt) {
  System.out.println("Starting data migration...");
  List<WeaviateObject<Map<String, Object>>> sourceObjects = StreamSupport
      .stream(collectionSrc.paginate(p -> p.includeVector()).spliterator(),
          false)
      .map(readObj -> WeaviateObject
          .<Map<String, Object>>of(c -> c.properties(readObj.properties())
              .uuid(readObj.uuid())
              .vectors(readObj.vectors())))
      .collect(Collectors.toList());

  collectionTgt.data.insertMany(sourceObjects);

  System.out.println("Data migration complete.");
}
```

```csharpraw title="C#"
private async Task MigrateData<T>(
    CollectionClient collectionSrc,
    CollectionClient collectionTgt
)
{
    Console.WriteLine("Starting data migration...");

    // Fetch source objects
    var response = await collectionSrc.Query.FetchObjects(limit: 10000, includeVectors: true);

    // Map to Strong Type List
    var sourceObjects = new List<T>();
    foreach (var obj in response.Objects)
    {
        // Deserialize the inner properties Dictionary to the POCO type
        var json = JsonSerializer.Serialize(obj.Properties);
        var typedObj = JsonSerializer.Deserialize<T>(json);
        if (typedObj != null)
        {
            sourceObjects.Add(typedObj);
        }
    }

    // InsertMany using Strong Types
    await collectionTgt.Data.InsertMany(sourceObjects.ToArray());

    Console.WriteLine($"Data migration complete. Migrated {sourceObjects.Count} objects.");
}
```
:::

## Related pages

- [Connect to Weaviate](../connect-to-weaviate/index.md)
- [Cursor API](../how-to-manage-objects/read-all-objects.md)
- [Multi-tenancy operations](multi-tenancy.md)

## Questions and feedback

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

::::card-grid
:::card{title="Community Forum" href="https://forum.weaviate.io/c/support" icon="messages-square"}
Ask questions and connect with other developers on our **Community forum**.
:::

:::card{title="Support" href="/guides/support-overview" icon="life-buoy"}
Weaviate Cloud user or customer? Find the right channel on the **Support page**.
:::
::::

## Related pages

- [Agents](./agents-index.md)
- [AI-assisted Weaviate code generation](./ai-assisted-vibe-coding-index.md)
- [APIs](./apis-index.md)
- [Authorization and authentication](./authorization-and-authentication-index.md)
- [Benchmarks](./benchmarks-index.md)
- [Best practices](./best-practices-index.md)
- [Client libraries](./clients-index.md)
- [Client Libraries / SDKs](./client-libraries-index.md)
- [Cloud](./cloud-index.md)
- [Cloud account management](./cloud-account-management-index.md)

# Agent Instructions

This portal answers questions programmatically. To receive a synthesized,
source-cited answer instead of crawling page by page, append the `?ask=`
query parameter to any page URL on this site:

    /guides/quickstart?ask=how+do+I+authenticate

Optional parameters:

- `&goal=<what-you-are-trying-to-do>` steers the answer toward your
  objective (e.g. `&goal=write+a+python+client`).
- `&version=<label>` scopes the answer to a mounted version when the
  portal publishes more than one.

The response is `text/markdown`: the answer followed by a `# Sources` list
of the portal pages it was grounded in. Status codes are the contract:

- `200` — the answer; `402` — the portal owner’s plan or answer credits are
  exhausted (surface this to your operator; do NOT retry); `429` — you are
  rate-limited; back off for the `Retry-After` seconds; `503` — the answer
  lane is temporarily unavailable; fall back to crawling the `.md` pages.

For the full corpus map read `llms.txt` at the site root; for the tool
surface (search + page fetch as MCP tools) see `/mcp`.
