---
title: "Reference: Upstash Vector Store | Vectors"
description: Documentation for the UpstashVector class in Mastra, which provides vector search using Upstash Vector.
packages:
  - "@mastra/core"
  - "@mastra/fastembed"
  - "@mastra/memory"
  - "@mastra/upstash"
---

# Upstash Vector Store

The UpstashVector class provides vector search using [Upstash Vector](https://upstash.com/vector), a serverless vector database service that provides vector similarity search with metadata filtering capabilities and hybrid search support.

## Constructor Options

<PropertiesTable
  content={[
    {
      name: "url",
      type: "string",
      description: "Upstash Vector database URL",
    },
    {
      name: "token",
      type: "string",
      description: "Upstash Vector API token",
    },
  ]}
/>

## Methods

### createIndex()

Note: This method is a no-op for Upstash as indexes are created automatically.

<PropertiesTable
  content={[
    {
      name: "indexName",
      type: "string",
      description: "Name of the index to create",
    },
    {
      name: "dimension",
      type: "number",
      description: "Vector dimension (must match your embedding model)",
    },
    {
      name: "metric",
      type: "'cosine' | 'euclidean' | 'dotproduct'",
      isOptional: true,
      defaultValue: "cosine",
      description: "Distance metric for similarity search",
    },
  ]}
/>

### upsert()

<PropertiesTable
  content={[
    {
      name: "indexName",
      type: "string",
      description: "Name of the index to upsert into",
    },
    {
      name: "vectors",
      type: "number[][]",
      description: "Array of embedding vectors",
    },
    {
      name: "sparseVectors",
      type: "{ indices: number[], values: number[] }[]",
      isOptional: true,
      description:
        "Array of sparse vectors for hybrid search. Each sparse vector must have matching indices and values arrays.",
    },
    {
      name: "metadata",
      type: "Record<string, any>[]",
      isOptional: true,
      description: "Metadata for each vector",
    },
    {
      name: "ids",
      type: "string[]",
      isOptional: true,
      description: "Optional vector IDs (auto-generated if not provided)",
    },
  ]}
/>

### query()

<PropertiesTable
  content={[
    {
      name: "indexName",
      type: "string",
      description: "Name of the index to query",
    },
    {
      name: "queryVector",
      type: "number[]",
      description: "Query vector to find similar vectors",
    },
    {
      name: "sparseVector",
      type: "{ indices: number[], values: number[] }",
      isOptional: true,
      description:
        "Optional sparse vector for hybrid search. Must have matching indices and values arrays.",
    },
    {
      name: "topK",
      type: "number",
      isOptional: true,
      defaultValue: "10",
      description: "Number of results to return",
    },
    {
      name: "filter",
      type: "Record<string, any>",
      isOptional: true,
      description: "Metadata filters for the query",
    },
    {
      name: "includeVector",
      type: "boolean",
      isOptional: true,
      defaultValue: "false",
      description: "Whether to include vectors in the results",
    },
    {
      name: "fusionAlgorithm",
      type: "FusionAlgorithm",
      isOptional: true,
      description:
        "Algorithm used to combine dense and sparse search results in hybrid search (e.g., RRF - Reciprocal Rank Fusion)",
    },
    {
      name: "queryMode",
      type: "QueryMode",
      isOptional: true,
      description:
        "Search mode: 'DENSE' for dense-only, 'SPARSE' for sparse-only, or 'HYBRID' for combined search",
    },
  ]}
/>

### listIndexes()

Returns an array of index names (namespaces) as strings.

### describeIndex()

<PropertiesTable
  content={[
    {
      name: "indexName",
      type: "string",
      description: "Name of the index to describe",
    },
  ]}
/>

Returns:

```typescript
interface IndexStats {
  dimension: number;
  count: number;
  metric: "cosine" | "euclidean" | "dotproduct";
}
```

### deleteIndex()

<PropertiesTable
  content={[
    {
      name: "indexName",
      type: "string",
      description: "Name of the index (namespace) to delete",
    },
  ]}
/>

### updateVector()

<PropertiesTable
  content={[
    {
      name: "indexName",
      type: "string",
      description: "Name of the index to update",
    },
    {
      name: "id",
      type: "string",
      description: "ID of the item to update",
    },
    {
      name: "update",
      type: "object",
      description:
        "Update object containing vector, sparse vector, and/or metadata",
    },
  ]}
/>

The `update` object can have the following properties:

- `vector` (optional): An array of numbers representing the new dense vector.
- `sparseVector` (optional): A sparse vector object with `indices` and `values` arrays for hybrid indexes.
- `metadata` (optional): A record of key-value pairs for metadata.

### deleteVector()

<PropertiesTable
  content={[
    {
      name: "indexName",
      type: "string",
      description: "Name of the index from which to delete the item",
    },
    {
      name: "id",
      type: "string",
      description: "ID of the item to delete",
    },
  ]}
/>

Attempts to delete an item by its ID from the specified index. Logs an error message if the deletion fails.

## Hybrid Vector Search

Upstash Vector supports hybrid search that combines semantic search (dense vectors) with keyword-based search (sparse vectors) for improved relevance and accuracy.

### Basic Hybrid Usage

```typescript
import { UpstashVector } from "@mastra/upstash";

const vectorStore = new UpstashVector({
  id: 'upstash-vector',
  url: process.env.UPSTASH_VECTOR_URL,
  token: process.env.UPSTASH_VECTOR_TOKEN,
});

// Upsert vectors with both dense and sparse components
const denseVectors = [
  [0.1, 0.2, 0.3],
  [0.4, 0.5, 0.6],
];
const sparseVectors = [
  { indices: [1, 5, 10], values: [0.8, 0.6, 0.4] },
  { indices: [2, 6, 11], values: [0.7, 0.5, 0.3] },
];

await vectorStore.upsert({
  indexName: "hybrid-index",
  vectors: denseVectors,
  sparseVectors: sparseVectors,
  metadata: [{ title: "Document 1" }, { title: "Document 2" }],
});

// Query with hybrid search
const results = await vectorStore.query({
  indexName: "hybrid-index",
  queryVector: [0.1, 0.2, 0.3],
  sparseVector: { indices: [1, 5], values: [0.9, 0.7] },
  topK: 10,
});
```

### Advanced Hybrid Search Options

```typescript
import { FusionAlgorithm, QueryMode } from "@upstash/vector";

// Query with specific fusion algorithm
const fusionResults = await vectorStore.query({
  indexName: "hybrid-index",
  queryVector: [0.1, 0.2, 0.3],
  sparseVector: { indices: [1, 5], values: [0.9, 0.7] },
  fusionAlgorithm: FusionAlgorithm.RRF,
  topK: 10,
});

// Dense-only search
const denseResults = await vectorStore.query({
  indexName: "hybrid-index",
  queryVector: [0.1, 0.2, 0.3],
  queryMode: QueryMode.DENSE,
  topK: 10,
});

// Sparse-only search
const sparseResults = await vectorStore.query({
  indexName: "hybrid-index",
  queryVector: [0.1, 0.2, 0.3], // Still required for index structure
  sparseVector: { indices: [1, 5], values: [0.9, 0.7] },
  queryMode: QueryMode.SPARSE,
  topK: 10,
});
```

### Updating Hybrid Vectors

```typescript
// Update both dense and sparse components
await vectorStore.updateVector({
  indexName: "hybrid-index",
  id: "vector-id",
  update: {
    vector: [0.2, 0.3, 0.4],
    sparseVector: { indices: [2, 7, 12], values: [0.9, 0.8, 0.6] },
    metadata: { title: "Updated Document" },
  },
});
```

## Response Types

Query results are returned in this format:

```typescript
interface QueryResult {
  id: string;
  score: number;
  metadata: Record<string, any>;
  vector?: number[]; // Only included if includeVector is true
}
```

## Error Handling

The store throws typed errors that can be caught:

```typescript
try {
  await store.query({
    indexName: "index_name",
    queryVector: queryVector,
  });
} catch (error) {
  if (error instanceof VectorStoreError) {
    console.log(error.code); // 'connection_failed' | 'invalid_dimension' | etc
    console.log(error.details); // Additional error context
  }
}
```

## Environment Variables

Required environment variables:

- `UPSTASH_VECTOR_URL`: Your Upstash Vector database URL
- `UPSTASH_VECTOR_TOKEN`: Your Upstash Vector API token

## Usage Example

### Local embeddings with fastembed

Embeddings are numeric vectors used by memory's `semanticRecall` to retrieve related messages by meaning (not keywords). This setup uses `@mastra/fastembed` to generate vector embeddings.

Install `fastembed` to get started:

```bash
npm install @mastra/fastembed@beta
```

Add the following to your agent:

```typescript title="src/mastra/agents/example-upstash-agent.ts"
import { Memory } from "@mastra/memory";
import { Agent } from "@mastra/core/agent";
import { UpstashStore, UpstashVector } from "@mastra/upstash";
import { fastembed } from "@mastra/fastembed";

export const upstashAgent = new Agent({
  id: "upstash-agent",
  name: "Upstash Agent",
  instructions:
    "You are an AI agent with the ability to automatically recall memories from previous interactions.",
  model: "openai/gpt-5.1",
  memory: new Memory({
    storage: new UpstashStore({
      id: 'upstash-agent-storage',
      url: process.env.UPSTASH_REDIS_REST_URL!,
      token: process.env.UPSTASH_REDIS_REST_TOKEN!,
    }),
    vector: new UpstashVector({
      id: 'upstash-agent-vector',
      url: process.env.UPSTASH_VECTOR_REST_URL!,
      token: process.env.UPSTASH_VECTOR_REST_TOKEN!,
    }),
    embedder: fastembed,
    options: {
      lastMessages: 10,
      semanticRecall: {
        topK: 3,
        messageRange: 2,
      },
    },
  }),
});
```

## Related

- [Metadata Filters](../rag/metadata-filters)
