Manage Snapshots
On RequestIn this guide, you will learn how to create and manage snapshots, including
This feature is available only for Dedicated clusters.
Create snapshot
Before creating a snapshot, you are advised to stop writing data to the target collection and call flush() to avoid possible data loss.
Calling flush() is not mandatory but highly recommended to avoid data loss. If you skip this, the snapshot contains only the data that has already been flushed.
When naming a snapshot, use clear, descriptive names, such as "daily_backup_20240101" or "v2.1_production_release" and avoid generic terms, such as "backup1" and "test". Use snapshot names wisely to distinguish snapshots across versions, environments, and stages.
The code examples below assume that you already have a collection named my_collection.
- Python
- Java
- Go
- Rust
- C++
- NodeJS
- CSharp
- cURL
from pymilvus import MilvusClient
client = MilvusClient(
uri="YOUR_CLUSTER_ENDPOINT",
token="YOUR_CLUSTER_TOKEN"
)
# Recommended: Flush data before creating snapshot to ensure all data is included
client.flush(collection_name="my_collection")
# Create snapshot for entire collection
client.create_snapshot(
collection_name="my_collection",
snapshot_name="backup_20240101",
description="Daily backup for January 1st, 2024"
)
import io.milvus.v2.client.ConnectConfig;
import io.milvus.v2.client.MilvusClientV2;
import io.milvus.v2.service.utility.request.FlushReq;
import java.util.Collections;
import io.milvus.v2.service.snapshot.request.CreateSnapshotReq;
import io.milvus.v2.service.snapshot.request.ListSnapshotsReq;
import io.milvus.v2.service.snapshot.request.DescribeSnapshotReq;
import io.milvus.v2.service.snapshot.request.PinSnapshotDataReq;
import io.milvus.v2.service.snapshot.request.UnpinSnapshotDataReq;
import io.milvus.v2.service.snapshot.request.RestoreSnapshotReq;
import io.milvus.v2.service.snapshot.request.DropSnapshotReq;
import io.milvus.v2.service.snapshot.request.ListRestoreSnapshotJobsReq;
import io.milvus.v2.service.snapshot.request.GetRestoreSnapshotStateReq;
ConnectConfig config = ConnectConfig.builder()
.uri("YOUR_CLUSTER_ENDPOINT")
.token("YOUR_CLUSTER_TOKEN")
.build();
MilvusClientV2 client = new MilvusClientV2(config);
// Recommended: Flush data before creating snapshot to ensure all data is included
client.flush(FlushReq.builder()
.collectionNames(Collections.singletonList("my_collection"))
.build());
// Create snapshot for entire collection
client.createSnapshot(CreateSnapshotReq.builder()
.collectionName("my_collection")
.snapshotName("backup_20240101")
.description("Daily backup for January 1st, 2024")
.build());
import (
"context"
"log"
"github.com/milvus-io/milvus/client/v3/milvusclient"
"fmt"
)
client, err := milvusclient.New(context.Background(), &milvusclient.ClientConfig{
Address: "YOUR_CLUSTER_ENDPOINT",
APIKey: "YOUR_CLUSTER_TOKEN",
})
if err != nil {
log.Fatal(err)
}
defer client.Close(context.Background())
// Recommended: Flush data before creating snapshot to ensure all data is included
_, err = client.Flush(context.Background(), milvusclient.NewFlushOption("my_collection"))
if err != nil {
log.Fatal(err)
}
// Create snapshot
createOpt := milvusclient.NewCreateSnapshotOption("backup_20240101", "my_collection").
WithDescription("Daily backup for January 1st, 2024")
err = client.CreateSnapshot(context.Background(), createOpt)
if err != nil {
log.Fatal(err)
}
use milvus::v2::error::Result;
use milvus::v2::prelude::*;
let config = ConnectConfig::new().uri("YOUR_CLUSTER_ENDPOINT").token("YOUR_CLUSTER_TOKEN");
let client = ClientV2::new(&config).await?;
// Recommended: Flush data before creating snapshot to ensure all data is included
client.flush(
FlushRequest::builder()
.collection_names(["my_collection"])
.build()?,
).await?;
// Create snapshot for entire collection
client.create_snapshot(
CreateSnapshotRequest::builder()
.collection_name("my_collection")
.snapshot_name("backup_20240101")
.description("Daily backup for January 1st, 2024")
.build()?,
).await?;
#include "milvus/MilvusClientV2.h"
#include <iostream>
#include <memory>
auto client = milvus::MilvusClientV2::Create();
milvus::ConnectParam connect_param{"YOUR_CLUSTER_ENDPOINT", "YOUR_CLUSTER_TOKEN"};
auto status = client->Connect(connect_param);
if (!status.IsOk()) {
std::cout << status.Message() << std::endl;
}
// Recommended: Flush data before creating snapshot to ensure all data is included
status = client->Flush(milvus::FlushRequest().WithCollectionNames({"my_collection"}));
if (!status.IsOk()) {
std::cout << status.Message() << std::endl;
}
// Create snapshot for entire collection
status = client->CreateSnapshot(milvus::CreateSnapshotRequest()
.WithCollectionName("my_collection")
.WithSnapshotName("backup_20240101")
.WithDescription("Daily backup for January 1st, 2024"));
if (!status.IsOk()) {
std::cout << status.Message() << std::endl;
}
import { MilvusClient } from '@zilliz/milvus2-sdk-node';
// node.js
const client = new MilvusClient({
address: 'YOUR_CLUSTER_ENDPOINT',
token: 'YOUR_CLUSTER_TOKEN'
});
// Recommended: Flush data before creating snapshot to ensure all data is included
await client.flush({ collection_names: ['my_collection'] });
// Create snapshot for entire collection
await client.createSnapshot({
collection_name: 'my_collection',
snapshot_name: 'backup_20240101',
description: 'Daily backup for January 1st, 2024'
});
using Milvus.Client.V2;
using Milvus.Client.V2.Requests.Snapshot;
using Milvus.Client.V2.Requests.Utility;
using Milvus.Client.V2.Types;
var config = new ConnectConfig
{
Uri = "YOUR_CLUSTER_ENDPOINT",
Username = "root",
Password = "Milvus"
};
using var client = new MilvusClientV2(config);
await client.ConnectAsync();
// Recommended: Flush data before creating snapshot to ensure all data is included
await client.FlushAsync(new FlushReq { CollectionNames = ["my_collection"] });
// Create snapshot for entire collection
await client.CreateSnapshotAsync(new CreateSnapshotReq
{
CollectionName = "my_collection",
SnapshotName = "backup_20240101",
Description = "Daily backup for January 1st, 2024"
});
# restful
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/collections/flush" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
-d '{
"collectionName": "my_collection"
}'
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/snapshots/create" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
-d '{
"collectionName": "my_collection",
"snapshotName": "backup_20240101",
"description": "Daily backup for January 1st, 2024"
}'
List snapshots
You can list the names of existing snapshots.
- Python
- Java
- Go
- Rust
- C++
- NodeJS
- CSharp
- cURL
# List all snapshots for a collection
snapshots = client.list_snapshots(
collection_name="my_collection"
)
// List all snapshots for a collection
client.listSnapshots(ListSnapshotsReq.builder()
.collectionName("my_collection")
.build());
// List snapshots for collection
listOpt := milvusclient.NewListSnapshotsOption("my_collection")
snapshots, err := client.ListSnapshots(context.Background(), listOpt)
if err != nil {
log.Fatal(err)
}
// List all snapshots for a collection
let snapshots = client.list_snapshots(
ListSnapshotsRequest::builder()
.collection_name("my_collection")
.build()?,
).await?;
println!("{:?}", snapshots);
// List snapshots for collection
milvus::ListSnapshotsResponse snapshots;
status = client->ListSnapshots(milvus::ListSnapshotsRequest()
.WithCollectionName("my_collection"),
snapshots);
if (!status.IsOk()) {
std::cout << status.Message() << std::endl;
}
// node.js
// List all snapshots for a collection
const snapshots = await client.listSnapshots({
collection_name: 'my_collection'
});
console.log(snapshots);
// List all snapshots for a collection
ListSnapshotsResp snapshots = await client.ListSnapshotsAsync(new ListSnapshotsReq
{
CollectionName = "my_collection"
});
foreach (string name in snapshots.Snapshots)
{
Console.WriteLine(name);
}
# restful
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/snapshots/list" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
-d '{
"collectionName": "my_collection"
}'
Describe snapshot
You can get the detailed information about a specific snapshot.
- Python
- Java
- Go
- Rust
- C++
- NodeJS
- CSharp
- cURL
snapshot_info = client.describe_snapshot(
snapshot_name="backup_20240101",
collection_name="my_collection",
)
print(f"Snapshot name: {snapshot_info.name}")
print(f"Collection: {snapshot_info.collection_name}")
print(f"Created: {snapshot_info.create_ts}")
print(f"Description: {snapshot_info.description}")
// Describe a snapshot
client.describeSnapshot(DescribeSnapshotReq.builder()
.collectionName("my_collection")
.snapshotName("backup_20240101")
.build());
describeOpt := milvusclient.NewDescribeSnapshotOption("backup_20240101", "my_collection")
resp, err := client.DescribeSnapshot(context.Background(), describeOpt)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Snapshot ID: %s\n", resp.GetName())
fmt.Printf("Collection: %s\n", resp.GetCollectionName())
// Describe a snapshot
let snapshot_info = client.describe_snapshot(
DescribeSnapshotRequest::builder()
.collection_name("my_collection")
.snapshot_name("backup_20240101")
.build()?,
).await?;
println!("{:?}", snapshot_info);
// Describe a snapshot
milvus::DescribeSnapshotResponse snapshot_info;
status = client->DescribeSnapshot(milvus::DescribeSnapshotRequest()
.WithCollectionName("my_collection")
.WithSnapshotName("backup_20240101"),
snapshot_info);
if (!status.IsOk()) {
std::cout << status.Message() << std::endl;
}
// node.js
// Describe a snapshot
const snapshot_info = await client.describeSnapshot({
collection_name: 'my_collection',
snapshot_name: 'backup_20240101'
});
console.log(snapshot_info);
// Describe a snapshot
DescribeSnapshotResp snapshotInfo = await client.DescribeSnapshotAsync(new DescribeSnapshotReq
{
CollectionName = "my_collection",
SnapshotName = "backup_20240101"
});
Console.WriteLine($"Snapshot name: {snapshotInfo.Name}");
Console.WriteLine($"Collection: {snapshotInfo.CollectionName}");
Console.WriteLine($"Created: {snapshotInfo.CreateTs}");
Console.WriteLine($"Description: {snapshotInfo.Description}");
# restful
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/snapshots/describe" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
-d '{
"collectionName": "my_collection",
"snapshotName": "backup_20240101"
}'
Pin/unpin snapshot data
During restoration, you can pin a snapshot to temporarily protect its underlying data from garbage collection, and unpin it to release the data.
You can also set a time-to-live (TTL) duration for the pin operation so that the pinned data will be released when the duration expires.
- Python
- Java
- Go
- Rust
- C++
- NodeJS
- CSharp
- cURL
pin_id = client.pin_snapshot_data(
snapshot_name="backup_20240101",
collection_name="my_collection",
ttl_seconds=3600,
)
client.unpin_snapshot_data(
pin_id=pin_id
)
Long pinId = client.pinSnapshotData(PinSnapshotDataReq.builder()
.collectionName("my_collection")
.snapshotName("backup_20240101")
.ttlSeconds(3600L)
.build()).getPinId();
client.unpinSnapshotData(UnpinSnapshotDataReq.builder()
.pinId(pinId)
.build());
pinID, err := client.PinSnapshotData(
context.Background(),
milvusclient.NewPinSnapshotDataOption("backup_20240101", "my_collection").WithTTL(3600),
)
if err != nil {
log.Fatal(err)
}
defer func() {
_ = client.UnpinSnapshotData(context.Background(), milvusclient.NewUnpinSnapshotDataOption(pinID))
}()
// do work with pinned snapshot data
// Pin snapshot data
let pin_id = client.pin_snapshot_data(
PinSnapshotDataRequest::builder()
.collection_name("my_collection")
.snapshot_name("backup_20240101")
.ttl_seconds(3600)
.build()?,
).await?.pin_id();
// Unpin snapshot data
client.unpin_snapshot_data(
UnpinSnapshotDataRequest::builder()
.pin_id(pin_id)
.build()?,
).await?;
// Pin snapshot data
milvus::PinSnapshotDataResponse pin_resp;
status = client->PinSnapshotData(milvus::PinSnapshotDataRequest()
.WithCollectionName("my_collection")
.WithSnapshotName("backup_20240101")
.WithTtlSeconds(3600),
pin_resp);
if (!status.IsOk()) {
std::cout << status.Message() << std::endl;
}
// Unpin snapshot data
status = client->UnpinSnapshotData(milvus::UnpinSnapshotDataRequest()
.WithPinID(pin_resp.PinID()));
if (!status.IsOk()) {
std::cout << status.Message() << std::endl;
}
// node.js
// Pin snapshot data
const pin_resp = await client.pinSnapshotData({
collection_name: 'my_collection',
snapshot_name: 'backup_20240101',
ttl_seconds: 3600
});
// Unpin snapshot data
await client.unpinSnapshotData({
pin_id: pin_resp.pin_id
});
// Pin snapshot data
long pinId = (await client.PinSnapshotDataAsync(new PinSnapshotDataReq
{
CollectionName = "my_collection",
SnapshotName = "backup_20240101",
TtlSeconds = 3600
})).PinId;
// Unpin snapshot data
await client.UnpinSnapshotDataAsync(new UnpinSnapshotDataReq
{
PinId = pinId
});
# restful
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/snapshots/pin" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
-d '{
"collectionName": "my_collection",
"snapshotName": "backup_20240101",
"ttlSeconds": 3600
}'
Restore snapshot
You can restore a snapshot to a new collection. This operation is asynchronous and returns a job ID for tracking the restoration progress.
The restoration uses a copy-segment mechanism instead of data import, which is more efficient because it
-
directly copies segment files (binlogs, deltalogs, index files) from snapshot storage
-
preserves field IDs and index IDs to ensure compatibility with existing data files
-
avoids data rewriting and index rebuilding, resulting in significantly faster restore times, and
-
ensures a 10- to 100-fold performance increase compared with traditional backup and restore methods
To restore a snapshot, do as follows:
- Python
- Java
- Go
- Rust
- C++
- NodeJS
- CSharp
- cURL
# Restore snapshot to new collection
job_id = client.restore_snapshot(
snapshot_name="backup_20240101",
source_collection_name="my_collection",
target_collection_name="restored_collection",
)
// Restore snapshot to new collection
client.restoreSnapshot(RestoreSnapshotReq.builder()
.sourceCollectionName("my_collection")
.targetCollectionName("restored_collection")
.snapshotName("backup_20240101")
.build());
restoreOpt := milvusclient.NewRestoreSnapshotOption(
"backup_20240101",
"my_collection",
"restored_collection",
)
jobID, err := client.RestoreSnapshot(context.Background(), restoreOpt)
if err != nil {
log.Fatal(err)
}
// Restore snapshot to new collection
let job_id = client.restore_snapshot(
RestoreSnapshotRequest::builder()
.snapshot_name("backup_20240101")
.source_collection_name("my_collection")
.target_collection_name("restored_collection")
.build()?,
).await?.job_id();
println!("job id: {}", job_id);
// Restore snapshot to new collection
milvus::RestoreSnapshotResponse restore_resp;
status = client->RestoreSnapshot(milvus::RestoreSnapshotRequest()
.WithSourceCollectionName("my_collection")
.WithSnapshotName("backup_20240101")
.WithTargetCollectionName("restored_collection"),
restore_resp);
if (!status.IsOk()) {
std::cout << status.Message() << std::endl;
}
// node.js
// Restore snapshot to new collection
const restore_resp = await client.restoreSnapshot({
source_collection_name: 'my_collection',
target_collection_name: 'restored_collection',
snapshot_name: 'backup_20240101'
});
console.log(restore_resp);
// Restore snapshot to new collection
long jobId = (await client.RestoreSnapshotAsync(new RestoreSnapshotReq
{
SnapshotName = "backup_20240101",
SourceCollectionName = "my_collection",
TargetCollectionName = "restored_collection"
})).JobId;
# restful
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/snapshots/restore" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
-d '{
"sourceCollectionName": "my_collection",
"targetCollectionName": "restored_collection",
"snapshotName": "backup_20240101"
}'
For details on monitoring the progress of a restoration job, refer to Monitor restoration progress.
Drop snapshot
You can drop a snapshot if it is no longer needed. You are advised to remove old snapshots regularly to save storage.
- Python
- Java
- Go
- Rust
- C++
- NodeJS
- CSharp
- cURL
client.drop_snapshot(
snapshot_name="backup_20240101",
collection_name="my_collection"
)
client.dropSnapshot(DropSnapshotReq.builder()
.collectionName("my_collection")
.snapshotName("backup_20240101")
.build());
dropOpt := milvusclient.NewDropSnapshotOption("backup_20240101", "my_collection")
err := client.DropSnapshot(context.Background(), dropOpt)
if err != nil {
log.Fatal(err)
}
client.drop_snapshot(
DropSnapshotRequest::builder()
.collection_name("my_collection")
.snapshot_name("backup_20240101")
.build()?,
).await?;
status = client->DropSnapshot(milvus::DropSnapshotRequest()
.WithCollectionName("my_collection")
.WithSnapshotName("backup_20240101"));
if (!status.IsOk()) {
std::cout << status.Message() << std::endl;
}
// node.js
await client.dropSnapshot({
collection_name: 'my_collection',
snapshot_name: 'backup_20240101'
});
await client.DropSnapshotAsync(new DropSnapshotReq
{
CollectionName = "my_collection",
SnapshotName = "backup_20240101"
});
# restful
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/snapshots/drop" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
-d '{
"collectionName": "my_collection",
"snapshotName": "backup_20240101"
}'
List restoration jobs
You can use this API to get a list of snapshots already created for the target collection.
- Python
- Java
- Go
- Rust
- C++
- NodeJS
- CSharp
- cURL
# List all restore jobs
jobs = client.list_restore_snapshot_jobs()
for job in jobs:
print(f"Job {job.job_id}: {job.snapshot_name} -> Collection {job.collection_name}")
print(f" State: {job.state}, Progress: {job.progress}%")
# List restore jobs for a specific collection
jobs = client.list_restore_snapshot_jobs(collection_name="my_collection")
// List all restore jobs
client.listRestoreSnapshotJobs(ListRestoreSnapshotJobsReq.builder()
.collectionName("my_collection")
.build());
for _, job := range jobs {
fmt.Printf("Job %d: %s -> Collection %s\n",
job.GetJobId(), job.GetSnapshotName(), job.GetCollectionName())
fmt.Printf(" State: %s, Progress: %d%%\n",
job.GetState().String(), job.GetProgress())
}
// List all restore jobs
let jobs = client.list_restore_snapshot_jobs(
ListRestoreSnapshotJobsRequest::builder()
.collection_name("my_collection")
.build()?,
).await?;
for job in jobs.jobs() {
println!("Job {}: {} -> Collection {}", job.get_job_id(), job.get_snapshot_name(), job.get_collection_name());
println!(" State: {:?}, Progress: {}%", job.get_state(), job.get_progress());
}
// List all restore jobs
milvus::ListRestoreSnapshotJobsResponse jobs;
status = client->ListRestoreSnapshotJobs(milvus::ListRestoreSnapshotJobsRequest()
.WithCollectionName("my_collection"),
jobs);
if (!status.IsOk()) {
std::cout << status.Message() << std::endl;
}
// node.js
// List all restore jobs
const jobs = await client.listRestoreSnapshotJobs({
collection_name: 'my_collection'
});
console.log(jobs);
// List all restore jobs
ListRestoreSnapshotJobsResp jobs = await client.ListRestoreSnapshotJobsAsync(new ListRestoreSnapshotJobsReq
{
CollectionName = "my_collection"
});
foreach (RestoreSnapshotJobInfo job in jobs.Jobs)
{
Console.WriteLine($"Job {job.JobId}: {job.SnapshotName} -> Collection {job.CollectionName}");
Console.WriteLine($" State: {job.State}, Progress: {job.Progress}%");
}
# restful
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/jobs/snapshot/list" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
-d '{
"collectionName": "my_collection"
}'
Get restoration state
Once you have a restoration job ID, you can use it to retrieve restoration progress.
- Python
- Java
- Go
- Rust
- C++
- NodeJS
- CSharp
- cURL
state = client.get_restore_snapshot_state(job_id=12345)
print(f"Job ID: {state.job_id}")
print(f"Snapshot Name: {state.snapshot_name}")
print(f"Collection: {state.collection_name}")
print(f"State: {state.state}")
print(f"Progress: {state.progress}%")
if state.state == "RestoreSnapshotFailed":
print(f"Failure Reason: {state.reason}")
print(f"Time Cost: {state.time_cost}ms")
// Get restoration state
client.getRestoreSnapshotState(GetRestoreSnapshotStateReq.builder()
.jobId(12345L)
.build());
stateOpt := milvusclient.NewGetRestoreSnapshotStateOption(12345)
state, err := client.GetRestoreSnapshotState(context.Background(), stateOpt)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Job ID: %d\n", state.GetJobId())
fmt.Printf("Snapshot Name: %s\n", state.GetSnapshotName())
fmt.Printf("Collection: %s\n", state.GetCollectionName())
fmt.Printf("State: %s\n", state.GetState().String())
fmt.Printf("Progress: %d%%\n", state.GetProgress())
fmt.Printf("Time Cost: %dms\n", state.GetTimeCost())
// Get restoration state
let state = client.get_restore_snapshot_state(
GetRestoreSnapshotStateRequest::builder()
.job_id(12345)
.build()?,
).await?;
println!("Job ID: {}", state.job_info().get_job_id());
println!("Snapshot Name: {}", state.job_info().get_snapshot_name());
println!("State: {:?}", state.job_info().get_state());
println!("Progress: {}%", state.job_info().get_progress());
// Get restoration state
milvus::GetRestoreSnapshotStateResponse state;
status = client->GetRestoreSnapshotState(milvus::GetRestoreSnapshotStateRequest()
.WithJobID(12345),
state);
if (!status.IsOk()) {
std::cout << status.Message() << std::endl;
}
// node.js
// Get restoration state
const state = await client.getRestoreSnapshotState({
job_id: 12345
});
console.log(state);
// Get restoration state
GetRestoreSnapshotStateResp state = await client.GetRestoreSnapshotStateAsync(new GetRestoreSnapshotStateReq
{
JobId = 12345
});
RestoreSnapshotJobInfo jobInfo = state.JobInfo;
Console.WriteLine($"Job ID: {jobInfo.JobId}");
Console.WriteLine($"Snapshot Name: {jobInfo.SnapshotName}");
Console.WriteLine($"Collection: {jobInfo.CollectionName}");
Console.WriteLine($"State: {jobInfo.State}");
Console.WriteLine($"Progress: {jobInfo.Progress}%");
Console.WriteLine($"Time Cost: {jobInfo.TimeCost}ms");
# restful
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/jobs/snapshot/describe" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
-d '{
"jobId": "12345"
}'