View a markdown version of this page

Using vector indexes in DynamoDB - Amazon DynamoDB

Using vector indexes in DynamoDB

Vector indexes are a type of index in Amazon DynamoDB that enable similarity search on vector embeddings stored in your table items. Unlike global secondary indexes and local secondary indexes, which support exact-match and range queries using Query and Scan operations, vector indexes use approximate nearest neighbor (ANN) search to find items whose vectors are most similar to a query vector that you provide. You perform these similarity searches by calling the SearchVectors API, which returns the most similar items ranked by a similarity score.

With vector indexes, you can store vector embeddings alongside your operational data in DynamoDB and perform similarity searches without needing a separate vector database. This eliminates the need for complex data replication pipelines between DynamoDB and external vector stores.

Vector indexes are managed through the same CreateTable and UpdateTable APIs that you already use, with the VectorIndexes parameter (for CreateTable) and the VectorIndexUpdates parameter (for UpdateTable).

Use cases for vector indexes

Vector indexes support a variety of use cases that involve finding similar items based on vector representations:

  • Semantic search – Build search engines that understand the meaning of queries rather than matching keywords. Store text embeddings generated by machine learning models and find semantically similar content.

  • Retrieval Augmented Generation (RAG) – Connect large language models (LLMs) with relevant knowledge bases. Store document embeddings in DynamoDB and retrieve the most relevant context for LLM prompts.

  • Recommendation systems – Find similar products, content, or users based on vector representations of their features or behavior.

  • AI agent memory – Store conversation embeddings to maintain context between sessions and improve AI agent performance.

  • Anomaly and fraud detection – Compare new events against embeddings of known-normal behavior to flag outliers, such as unusual transactions or fraudulent activity.

Comparing vector indexes with secondary indexes

The following table compares vector indexes with global secondary indexes and local secondary indexes.

Feature Vector index Global secondary index Local secondary index
Query type Similarity search Exact match and range Exact match and range
Read API SearchVectors Query, Scan Query, Scan
Schema Vector attribute, plus optional SearchSchema (partition key, inline filters) Partition key(s) and optional sort key(s) Same partition key, different sort key
Maximum per table 5 20 5
Capacity mode On-demand only On-demand or provisioned On-demand or provisioned

Distance functions

When you create a vector index, you choose a distance function. The distance function determines how DynamoDB measures similarity between vectors. Your choice affects ranking quality and search accuracy. Amazon DynamoDB supports three distance functions.

Distance function Score interpretation Best match
COSINE Lower scores indicate greater similarity. Measures the cosine distance (1 minus cosine similarity) between two vectors. Values range from 0 (identical direction) to 2 (opposite direction). Smallest scores
DOT_PRODUCT Higher scores indicate greater similarity. Measures the dot product between two vectors. Highest scores
EUCLIDEAN Lower scores indicate greater similarity. Measures the straight-line distance between two vectors. Smallest scores

To compare how distance functions rank the same query vector, see How distance functions rank results.

The following guidance helps you choose the right distance function for your workload.

COSINE

Compares direction and ignores magnitude. Use COSINE for semantic similarity with text embedding models. These models encode meaning in direction, and vector length can vary. Examples include Amazon Titan Text Embeddings and Cohere Embed.

COSINE is well suited for the following use cases:

  • Semantic search over product descriptions or documents

  • Retrieval Augmented Generation (RAG)

  • FAQ matching

COSINE is the safe default when you are unsure which function to use.

DOT_PRODUCT

DOT_PRODUCT is sensitive to both direction and magnitude (the length of a vector). Choose DOT_PRODUCT when your embedding model's documentation recommends dot product as the similarity measure, or when you want vector length to influence ranking.

DOT_PRODUCT is well suited for the following use cases:

  • Recommendation systems that use popularity or confidence scores to scale embeddings and influence ranking

  • Models whose documentation specifically recommends dot product as the similarity measure

  • Magnitude-sensitive ranking where vector length carries meaningful signal

We recommend normalizing your embeddings to unit length. When normalized, DOT_PRODUCT ranks results the same way as COSINE. Skip normalization only if you want magnitude to affect ranking.

Example use case: a product recommendation system where you scale each product embedding by its popularity score. More popular products get longer vectors and rank higher in search results.

EUCLIDEAN

Measures straight-line distance between two vectors. EUCLIDEAN is sensitive to magnitude. Use it when absolute position in the embedding space matters.

EUCLIDEAN is well suited for the following use cases:

  • Image or audio embeddings where spatial distance matters

  • Near-duplicate detection

  • Clustering and anomaly detection

Example use case: finding near-duplicate images from image embeddings.

Choose a distance function that matches your embedding model

If you are unsure which function to use, check your embedding model's documentation. Validate your choice against a representative dataset. You cannot change the distance function after index creation. For more information, see Match the distance function to your embeddings.

How distance functions rank results

The distance function you choose when you create the index determines both the Score value and the sort order of results. The same query can rank the same items differently under different distance functions. The following example uses the query vector [1, 0, 0, 0] against four stored vectors.

Stored vector COSINE (lower is more similar) EUCLIDEAN (lower is more similar) DOT_PRODUCT (higher is more similar)
[1, 0, 0, 0] 0.0 0.0 1.0
[10, 0, 0, 0] 0.0 9.0 10.0
[0.7071, 0.7071, 0, 0] 0.29 0.77 0.71
[-1, 0, 0, 0] 2.0 2.0 -1.0

Two behaviors are worth noting:

  • COSINE ignores magnitude. It scores [1, 0, 0, 0] and [10, 0, 0, 0] identically (both 0.0) because they point in the same direction. EUCLIDEAN ranks [10, 0, 0, 0] last for the same query because it measures absolute distance, which increases with a vector's magnitude.

  • DOT_PRODUCT scores can be negative. A vector pointing in the opposite direction ([-1, 0, 0, 0]) scores -1.0. Do not assume scores are always non-negative when you sort or apply thresholds to results.

SearchSchema

When you create a vector index, you can optionally define a SearchSchema that specifies vector index partition keys and inline filter attributes.

HASH (vector index partition key)

A vector index partition key partitions your index data for independent scaling. When you specify a vector index partition key, items with the same partition key value are stored together, which enables the system to search only the relevant data. At high scale, this lowers search latency because the search examines only a subset of the vector space instead of the entire index. Use attributes with low-to-medium cardinality, such as Category or Country. You can specify at most one vector index partition key.

If you define a vector index partition key in the SearchSchema, you must provide its value in the SearchConditionExpression when you call SearchVectors.

Use a partition key to scale search throughput

Define a vector index partition key when you expect a large index or high search volume. Because each SearchVectors call is scoped to a single partition key value, distributing your data across many partition key values lets you run more search operations per second and reduces the amount of data each search examines. See Choose a partition key that matches your query patterns.

INLINE_FILTER

Inline filter attributes are projected into the vector index so that DynamoDB can filter during search at the storage layer.

Inline filters support the equality operator (=) in SearchConditionExpression. Comparison, range, and set-membership operators (<>, <, <=, >, >=, IN) are not yet available. Unlike vector index partition keys, inline filters are optional during search.

You can create a vector index without defining a partition key in the SearchSchema. In this case, every SearchVectors call searches the entire index. This is simpler because you don't need a SearchConditionExpression, but it does not scale horizontally. As your index grows, each search examines more data, increasing latency and cost. If your workload requires high throughput or your index contains a large number of vectors, define a partition key to distribute data across partitions and scale independently. See Choose a partition key that matches your query patterns.

Projections

Like global secondary indexes, vector indexes support projections that control which attributes from the base table are copied into the index. You specify the projection when you create the vector index.

  • KEYS_ONLY — Only the base table primary key attributes, the vector attribute, and any inline filter attributes defined in the SearchSchema are projected into the index.

  • INCLUDE — In addition to KEYS_ONLY attributes, you specify additional non-key attributes to project. You cannot change the set of included attributes after the vector index is created. To project a different set of attributes, delete the index and re-create it with the projection you want.

  • ALL — All attributes from the base table are projected into the index.

Projection limits what SearchVectors can return

Attributes that are not projected into the vector index cannot be returned in SearchVectors responses. If you need specific attributes in search results, include them in the projection or use ALL.

Using vector indexes with other DynamoDB features

DynamoDB Streams

You can enable DynamoDB Streams on a table that has a vector index, either with the StreamSpecification parameter when you create the table or through UpdateTable. The stream captures item-level changes to the base table, and operates independently of the vector index.

Global tables

You can add a vector index to a global table, and you can convert a table that has a vector index into a global table by adding a replica with UpdateTable. The vector index definition, including its dimensions, distance function, SearchSchema, and projection, is replicated automatically to each new replica Region. You do not create the vector index separately in the replica Region.

Items that you write in any replica Region are replicated to the other Regions and indexed there. After replication completes, SearchVectors in each Region searches the same set of vectors. Because vector search uses approximate nearest neighbor (ANN), separate searches in different Regions might return slightly different results or ordering for the same query, even over identical data. Replication and indexing of vectors in the other Regions are asynchronous, even for multi-Region strong consistency (MRSC) global tables. A vector that you just wrote in one Region might not yet appear in SearchVectors results in another Region until the change has propagated.

On-demand capacity required

Vector indexes require on-demand capacity mode, which global tables also support. Create the vector index and the replica on a table that already uses on-demand capacity.

Point-in-time recovery (PITR) and backups

When you restore a table from a point-in-time recovery or an on-demand backup, DynamoDB restores the base table data and the vector index definition. As with global secondary indexes, DynamoDB rebuilds the vector index from the restored base table data rather than copying it byte-for-byte, so the index goes through backfilling before it is ready for search. Wait until IndexStatus is ACTIVE and Backfilling is false on the restored index before you run SearchVectors.

Time to Live (TTL)

You can use DynamoDB TTL on a table that has a vector index. When TTL deletes an expired item from the base table, DynamoDB removes the corresponding entry from the vector index, the same way a manual delete does. Expired items therefore stop appearing in SearchVectors results after the deletion propagates to the index.

Importing and exporting table data

You can export a table that has a vector index to Amazon S3; the export contains the base table items, including the vector attributes stored on them. When you import data from Amazon S3 into a new table, define the vector index in the import request the same way you would with CreateTable. DynamoDB indexes the imported items as they are written, and the vector index becomes available after the import completes.

DAX

DynamoDB Accelerator (DAX) does not support the SearchVectors operation. Send SearchVectors requests directly to DynamoDB, even when your application uses DAX for other read operations. DAX caching of base table reads is unaffected by the presence of a vector index.