Skip to main content
doc0blade47/mem0documentation home
Sign in

Cloud Vector Backends

Last updated Oct 11, 2026100% grounded
Relevant source files

The following files were used as context for generating this wiki page:

Overview

Cloud vector backends provide scalable, managed infrastructure for high-dimensional vector persistence and approximate nearest neighbor (ANN) retrieval across distributed cloud storage engines and managed database services. These storage backends form the core persistence layer for memory management systems, handling vector insertions, multi-tenant namespace isolation, metadata filtering, and hybrid sparse-dense keyword searches. By abstracting diverse remote protocols—ranging from object-backed S3 endpoints and serverless HTTP APIs to graph analytics engines and distributed index clusters—these drivers enable uniform vector operations across both Python and TypeScript runtimes.

Sources: mem0/vector_stores/s3_vectors.py:24-181, mem0-ts/src/oss/src/vector_stores/s3_vectors.ts:35-242, mem0/vector_stores/neptune_analytics.py:41-199, mem0-ts/src/oss/src/vector_stores/neptune_analytics.ts:42-240, mem0/vector_stores/turbopuffer.py:25-207, mem0-ts/src/oss/src/vector_stores/turbopuffer.ts:13-212, mem0-ts/src/oss/src/vector_stores/qdrant.ts:300-412, mem0/vector_stores/milvus.py:33-146, mem0-ts/src/oss/src/vector_stores/milvus.ts:272-335, mem0/vector_stores/pinecone.py:25-121, mem0-ts/src/oss/src/vector_stores/pinecone.ts:244-289, mem0/vector_stores/weaviate.py:31-157, mem0-ts/src/oss/src/vector_stores/weaviate.ts:31-237, mem0/vector_stores/upstash_vector.py:41-172, mem0-ts/src/oss/src/vector_stores/upstash_vector.ts:17-268

Cloud Vector Driver Abstractions

Architectural Contract and Client Initialization

Cloud vector storage drivers implement a standard interface across both Python and TypeScript runtimes, wrapping diverse remote SDKs like boto3, @aws-sdk/client-s3vectors, and weaviate-client. Initialization routines handle optional peer dependencies dynamically, establish remote connections across HTTP, gRPC, or custom client parameters, and provision underlying vector buckets, indices, or classes.

Sources: mem0/vector_stores/s3_vectors.py:24-41, mem0-ts/src/oss/src/vector_stores/s3_vectors.ts:35-123, mem0/vector_stores/weaviate.py:31-85, mem0-ts/src/oss/src/vector_stores/weaviate.ts:31-118

Note

Optional SDK peer dependencies such as @aws-sdk/client-s3vectors and weaviate-client are lazily imported at runtime in TypeScript and safely caught behind missing-import exceptions in Python to keep base package installations lightweight for consumers who exclude specific cloud backends.

Sources: mem0/vector_stores/s3_vectors.py:9-13, mem0-ts/src/oss/src/vector_stores/s3_vectors.ts:69-82, mem0/vector_stores/weaviate.py:9-13, mem0-ts/src/oss/src/vector_stores/weaviate.ts:49-59

Lifecycle Hooks and Data Operations

Drivers manage the complete entity lifecycle across insertion, vector search, metadata filtering, retrieval, updates, and deletion. Depending on the engine capabilities, updates are handled either via direct object overwrites, native upsert batches, or pre-flight fetching to resolve missing vector payloads.

OperationPython MethodTypeScript MethodCore Responsibility
Insertinsert(...)insert(...)Batch writing of vectors, IDs, and metadata payloads into indices or collections.
Searchsearch(...)search(...)Approximate nearest neighbor vector query with optional metadata filters and top-$k$ limits.
Getget(...)get(...)Retrieval of stored vector record details and metadata by primary identifier.
Updateupdate(...)update(...)Modification of vector data or associated payload properties, handling missing parameters via pre-flight lookups.
Deletedelete(...)delete(...)Removal of individual vector entries by identifier.

Sources: mem0/vector_stores/s3_vectors.py:98-181, mem0-ts/src/oss/src/vector_stores/s3_vectors.ts:125-242, mem0/vector_stores/weaviate.py:158-199, mem0-ts/src/oss/src/vector_stores/weaviate.ts:128-204

Warning

When executing metadata-only updates in S3 Vectors where vector=None, the driver must fetch the existing vector payload beforehand; passing None directly to put_vectors triggers parameter validation errors in the underlying SDK.

Sources: mem0/vector_stores/s3_vectors.py:136-168

S3 Vectors Storage Architecture

The S3 Vectors driver provisions and interacts with object-backed storage collections across Python and TypeScript runtimes using boto3 and @aws-sdk/client-s3vectors. Initialization ensures that both the target vector bucket and the specified index exist before executing any operations, catching NotFoundException errors from remote service calls to trigger bucket and index creation automatically.

Sources: mem0/vector_stores/s3_vectors.py:39-70, mem0-ts/src/oss/src/vector_stores/s3_vectors.ts:116-123

Bucket and index provisioning operations configure data types, vector dimensions, and distance metrics. The supported index configurations and initialization parameters handle dimensional assertions across runtimes.

Configuration ParameterPython TypeTypeScript TypeDefault ValuePurpose
vectorBucketNamestrstringRequiredTarget S3 bucket container name for vector objects.
collectionName / collectionNamestrstringRequiredIndex or collection namespace within the vector bucket.
embeddingModelDims / dimensionintnumberRequiredDimensionality of the stored vector embeddings.
distanceMetricstr"cosine" | "euclidean""cosine"Distance calculation metric for similarity searches.
region_name / regionOptional[str]stringundefinedAWS region hosting the S3 Vectors client.

Sources: mem0/vector_stores/s3_vectors.py:25-37, mem0-ts/src/oss/src/vector_stores/s3_vectors.ts:17-29, mem0-ts/src/oss/src/vector_stores/s3_vectors.ts:47-65

Note

Distance score normalization maps raw engine distances into bounded similarity scores. Euclidean distances use an inverse monotonic transformation 1.0 / (1.0 + raw_distance) since they are unbounded, whereas cosine distances clip 1.0 - raw_distance at 0.0.

Sources: mem0/vector_stores/s3_vectors.py:72-80

Qdrant and Milvus Ingestion

Collection Provisioning and Schema Detection

Qdrant and Milvus drivers handle collection provisioning and schema detection differently depending on whether hybrid keyword search is enabled. In Milvus, collection initialization checks whether an existing collection contains both text and sparse fields, setting an internal _has_bm25_schema flag accordingly. When creating a fresh collection, Milvus defines fields for id (VARCHAR up to 512 characters, primary key), vectors (FLOAT_VECTOR with custom dimensions), metadata (JSON), text (VARCHAR up to 65535 characters with analyzer enabled), and sparse (SPARSE_FLOAT_VECTOR). It then adds a BM25 function linking text to sparse, applies an AUTOINDEX index on vectors, and adds a SPARSE_INVERTED_INDEX index named sparse_index with metric type BM25.

Sources: mem0/vector_stores/milvus.py:53-124

Warning

If an existing Milvus collection predates v3 hybrid search and lacks text or sparse fields, BM25 keyword scoring is disabled for that collection with a warning logger call, and writing an unknown top-level text field will cause insertion rejections.

Sources: mem0/vector_stores/milvus.py:80-90

Point Upsert Protocols and Hybrid Handling

Point insertion and upsert workflows adapt to server-side inference capabilities. In Qdrant, point vector building inspects _has_bm25_slot. Without a BM25 slot, it returns the plain dense vector array. When a BM25 slot is active, it builds a named vector map containing "" for the dense vector and a sparse query object for the BM25 vector name using text extracted from payload.textLemmatized or payload.data.

private async upsertPoints(
  points: { id: string | number; vector: any; payload?: any }[],
): Promise<void> {
  try {
    await this.client.upsert(this.collectionName, { points: points as any });
  } catch (error) {
    if (!this._hasBm25Slot) {
      throw error;
    }
    this._hasBm25Slot = false;
    console.warn(
      `Qdrant rejected the server-side BM25 vector for collection '${this.collectionName}'; ` +
        "disabling hybrid keyword search. This requires Qdrant >= 1.15.2 with inference enabled. " +
        "Retrying the write with a plain dense vector.",
    );
    const denseOnly = points.map((p) => ({
      ...p,
      vector: Array.isArray(p.vector) ? p.vector : p.vector[""],
    }));
    await this.client.upsert(this.collectionName, {
      points: denseOnly as any,
    });
  }
}

Sources: mem0-ts/src/oss/src/vector_stores/qdrant.ts:320-343

Note

Qdrant client types predate server-side sparse_vectors. Because older server versions (Qdrant < 1.15.2 or unactivated clusters) reject server-side BM25 configs during upsert, the driver catches the first upsert failure, disables _has_bm25_slot, and transparently retries the write using a plain dense vector.

Sources: mem0-ts/src/oss/src/vector_stores/qdrant.ts:312-343

In Milvus, record construction for insertion and updates similarly checks _has_bm25_schema. If the schema supports BM25, the record includes a text field populated by extracting text_lemmatized or data from metadata and slicing it to a maximum of 65,535 characters.

async insert(
  vectors: number[][],
  ids: string[],
  payloads: Record<string, any>[],
): Promise<void> {
  const data = vectors.map((vector, idx) => {
    const metadata = payloads[idx] || {};
    const row: Record<string, any> = {
      id: ids[idx],
      vectors: vector,
      metadata,
    };
    // Only write `text` when the collection has the BM25 schema; legacy
    // collections reject an unknown top-level field.
    if (this.hasBm25Schema) row.text = this.bm25Text(metadata);
    return row;
  });
  await this.client.insert({
    collection_name: this.collectionName,
    data,
  });
}

Sources: mem0-ts/src/oss/src/vector_stores/milvus.ts:272-293, mem0/vector_stores/milvus.py:126-146

Pinecone Namespacing and Operations

Index Resolution and Namespace Isolation

Pinecone client initialization resolves indices through either explicit client instances or API keys retrieved from parameters or the PINECONE_API_KEY environment variable. When creating or binding to collections, the driver checks existing indexes via list_cols().names() in Python, creating a new serverless or pod-based index if absent using either ServerlessSpec or PodSpec. Serverless configurations default to AWS region us-west-2 if no explicit configuration dictionary is supplied. Namespace isolation is maintained by passing the configured namespace string directly into query, upsert, fetch, and delete operations.

Sources: mem0/vector_stores/pinecone.py:58-123

Note

Deletion behavior varies based on whether a namespace is configured. If a namespace is set, delete_col() clears only that specific namespace via delete(delete_all=True, namespace=...). If namespace is None, it deletes the entire index collection.

Sources: mem0/vector_stores/pinecone.py:361-371, mem0-ts/src/oss/src/vector_stores/pinecone.ts:318-330

Filter Operator Mapping and Migrations

Metadata filtering maps domain filter operators to Pinecone-compatible selector syntax. The driver translates comparison operators such as equality, bounds, and inclusion sets into standard Pinecone expression keys.

Operator KeyPinecone Selector
eq$eq
ne$ne
gt$gt
gte$gte
lt$lt
lte$lte
in$in
nin$nin

Sources: mem0/vector_stores/pinecone.py:189-222, mem0-ts/src/oss/src/vector_stores/pinecone.ts:209-242

Warning

Text containment filters (contains and icontains) are unsupported by Pinecone metadata filters; the TypeScript driver skips them with a console warning, whereas unknown operators trigger an explicit runtime error.

Sources: mem0-ts/src/oss/src/vector_stores/pinecone.ts:220-230

Weaviate Class and Filter Mechanics

Weaviate Class Collections and Client Initialization

Connection Schemes and Local Setup

The Weaviate driver supports three distinct connection pathways across both Python and TypeScript runtimes: local development instances, managed Weaviate Cloud instances via API keys, and custom HTTP/gRPC host targets.

Connection ModeTrigger ConditionInitialization Method (Python)Initialization Method (TypeScript)
Localcluster_url contains "localhost"weaviate.connect_to_local()weaviate.connectToLocal()
Cloudauth_client_secret or apiKey presentweaviate.connect_to_weaviate_cloud()weaviate.connectToWeaviateCloud()
CustomDefault fallback when URL is providedweaviate.connect_to_custom()weaviate.connectToCustom()

Sources: mem0/vector_stores/weaviate.py:51-80, mem0-ts/src/oss/src/vector_stores/weaviate.ts:64-96

Note

When connecting via the custom fallback mode, the driver automatically targets gRPC port 50051 with insecure transport (grpcSecure: false), while inspecting the URL scheme to set the HTTP port to 443 for HTTPS or 8080 for plain HTTP.

Sources: mem0/vector_stores/weaviate.py:60-79, mem0-ts/src/oss/src/vector_stores/weaviate.ts:81-95

Schema Properties and Collection Creation

Collections are configured with a standard set of text-typed properties and an HNSW vector index combined with a none vectorizer configuration.

properties = [
    wvcc.Property(name="ids", data_type=wvcc.DataType.TEXT),
    wvcc.Property(name="hash", data_type=wvcc.DataType.TEXT),
    wvcc.Property(
        name="metadata",
        data_type=wvcc.DataType.TEXT,
        description="Additional metadata",
    ),
    wvcc.Property(name="data", data_type=wvcc.DataType.TEXT),
    wvcc.Property(name="created_at", data_type=wvcc.DataType.TEXT),
    wvcc.Property(name="category", data_type=wvcc.DataType.TEXT),
    wvcc.Property(name="updated_at", data_type=wvcc.DataType.TEXT),
    wvcc.Property(name="user_id", data_type=wvcc.DataType.TEXT),
    wvcc.Property(name="agent_id", data_type=wvcc.DataType.TEXT),
    wvcc.Property(name="run_id", data_type=wvcc.DataType.TEXT),
]
 
vectorizer_config = wvcc.Configure.Vectorizer.none()
vector_index_config = wvcc.Configure.VectorIndex.hnsw()
 
self.client.collections.create(
    self.collection_name,
    vectorizer_config=vectorizer_config,
    vector_index_config=vector_index_config,
    properties=properties,
)

Sources: mem0/vector_stores/weaviate.py:131-156, mem0-ts/src/oss/src/vector_stores/weaviate.ts:18-29, mem0-ts/src/oss/src/vector_stores/weaviate.ts:104-115

Vector Search Filter Compilation

Metadata search filters are compiled into Weaviate filter expressions by inspecting query keys for user_id, agent_id, and run_id. The drivers construct property-level equality checks and combine them using logical conjunction.

collection = self.client.collections.get(str(self.collection_name))
filter_conditions = []
if filters:
    for key, value in filters.items():
        if value and key in ["user_id", "agent_id", "run_id"]:
            filter_conditions.append(Filter.by_property(key).equal(value))
combined_filter = Filter.all_of(filter_conditions) if filter_conditions else None

Sources: mem0/vector_stores/weaviate.py:187-193, mem0-ts/src/oss/src/vector_stores/weaviate.ts:120-126

Warning

During object insertion, the Python driver explicitly checks if an ids key exists within the payload dictionary and deletes it to prevent conflicts with Weaviate's native object UUID assignment.

Sources: mem0/vector_stores/weaviate.py:175-178

Turbopuffer and Upstash Serverless Models

Serverless Namespace Queries and Row Parsing

Serverless vector backends delegate index lifecycle management and scaling to cloud infrastructure, exposing storage through lightweight namespace abstractions. The Turbopuffer driver structures vector collections as isolated namespaces that support implicit creation on first write. During similarity queries, result rows are parsed from model dumps where distance metrics—such as unbounded squared-L2 distances or cosine metrics—are normalized into bounded scores.

results = []
for row in rows:
    row_dict = row.model_dump()
    row_id = str(row_dict.pop("id"))
    dist = row_dict.pop("$dist", None)
    row_dict.pop("vector", None)
 
    if dist is None:
        score = None
    elif self.distance_metric == "euclidean_squared":
        # $dist is unbounded squared-L2 (lower = closer); map to a bounded
        # higher-is-better score, mirroring milvus/baidu. Cosine returns 1 - dist.
        score = 1.0 / (1.0 + dist)
    else:
        score = 1 - dist
 
    results.append(OutputData(
        id=row_id,
        score=score,
        payload=row_dict,
    ))
return results

Sources: mem0/vector_stores/turbopuffer.py:64-71, mem0/vector_stores/turbopuffer.py:118-139, mem0-ts/src/oss/src/vector_stores/turbopuffer.ts:68-80

Note

When the distance metric is configured to euclidean_squared, Turbopuffer returns unbounded squared-L2 values where lower numbers indicate closer proximity. The parser transforms these distances into higher-is-better relevance scores via the inverse mapping 1.0 / (1.0 + dist).

Sources: mem0/vector_stores/turbopuffer.py:127-130

Stringified Metadata Validation and Filter Construction

Upstash Vector enforces strict type validation for search and listing filters before transmitting expressions to the serverless endpoint. Filter keys are verified, and values must conform to primitive types (str, int, float, or bool). Furthermore, string values undergo strict validation to prevent query injection or syntax corruption.

if not isinstance(value, (str, int, float, bool)):
    raise ValueError(
        f"Filter value for {key!r} must be str, int, float, or bool, "
        f"got {type(value).__name__}"
    )
if isinstance(value, str) and ('"' in value or "\\" in value):
    raise ValueError(
        f"Filter value for {key!r} contains prohibited characters "
        f"(double quote or backslash): {value!r}"
    )

Sources: mem0/vector_stores/upstash_vector.py:23-32, mem0-ts/src/oss/src/vector_stores/upstash_vector.ts:229-239

Warning

Filter values of type string submitted to Upstash Vector cannot contain double quotes (") or backslashes (\). Any matching characters trigger an explicit ValueError during filter preprocessing.

Sources: mem0/vector_stores/upstash_vector.py:28-32

Was this page helpful?