On 5 August 2026 DynamoDB got native vector search. The interesting part is not that DynamoDB can run similarity queries, since several AWS services already do that. It is that the embedding is an ordinary attribute on an ordinary item, so the row and the vector that represents it commit in the same PutItem. This post covers what shipped, why that single write matters, the two use cases it fits best, and what to watch before building on it.

What shipped
Vector indexes are created through the APIs you already use: a VectorIndexes parameter on CreateTable, or VectorIndexUpdates on UpdateTable to add one to a table that already exists. Reads go through a new SearchVectors API, which takes a query vector, a TopK, and optional filters. Query, Scan, and PartiQL do not work against a vector index.
The embedding is a List of Number, written like any other attribute:
client
.put_item()
.table_name("documents")
.item("pk", AttributeValue::S(doc_id))
.item("category", AttributeValue::S(category))
.item("body", AttributeValue::S(body))
.item(
"embedding",
AttributeValue::L(
embedding
.iter()
.map(|f| AttributeValue::N(f.to_string()))
.collect(),
),
)
.send()
.await?;
AWS publishes single-digit millisecond latency at 99%+ recall on an approximate nearest neighbour search designed to hold trillions of vectors. An index takes up to 4,096 dimensions, uses one of three distance functions (COSINE, DOT_PRODUCT, or EUCLIDEAN), and returns at most 100 results per request.
One write instead of two
The shape this replaces is an operational store plus a separate vector store, with a replication pipeline between them: DynamoDB Streams feeding a Lambda that writes the vector to OpenSearch, Pinecone, or pgvector.
That pipeline is where the failure lives. The item write commits, the vector write fails or lands late, and the two stores disagree about the same document. Retrieval returns a chunk whose embedding matched the query, the application fetches the current row to build the prompt, and the model is handed text that does not match the reason it was retrieved. Nothing errors, the answer is just wrong, and the only way to find out is to compare the two stores against each other.
A single PutItem carrying both removes that. One write, one commit, nothing to reconcile, and no stream consumer, dead letter queue, or backfill job to operate. The write is still an ordinary DynamoDB write, so the conditional-write machinery works on it unchanged.
Where it fits
Retrieval-augmented generation. The document and its embedding live in the same item, so ingestion is one call and there is no pipeline to keep in sync. One caveat on the latency argument: SearchVectors cannot return an attribute that was not projected into the index, and AWS recommends projecting narrowly and doing a follow-up GetItem for the rest. What co-location removes for certain is the replication pipeline and the write roundtrip, not necessarily a second read.
Recommendations. Store an item’s feature vector on the item itself and find similar ones by proximity. DOT_PRODUCT is the distance function for this if you scale embeddings by something like a popularity score so more popular items rank higher. Normalise to unit length and use COSINE otherwise.
What to watch
- The write is atomic, the indexing is not. DynamoDB replicates into the index asynchronously, so there is a delay before a vector is searchable. That holds even under multi-region strong consistency, which covers the table and not the index. There is no read-your-write on search.
- DynamoDB never recomputes embeddings. Change the source text and the index keeps serving the old vector until you write a new one. A Streams-driven regeneration job still applies.
- The SearchSchema partition key is the main design decision. Without one, every search examines the whole index. With one, each search scopes to a single value. Cardinality that is too high leaves no neighbours to compare against and recall collapses; too low gives no throughput scaling.
- Cost is metered in bytes, not capacity units, as
VectorSearchRequestBytesandVectorWriteRequestBytes, with a 1 KB per-request floor. AWS’s guidance is to measure it on a representative dataset rather than estimate from dimension count. - The hard constraints. On-demand capacity only, and the base table has to be on-demand too. Dimensions and distance function are fixed at creation. Inline filters support equality only. No DAX, no fine-grained access control on
SearchVectors, no pagination, 16 MB response cap.
Closing
Keeping the embedding on the item is a good fit for serverless work. There is no cluster to size and nothing to keep warm, ingestion is one PutItem and retrieval is one SearchVectors call, and both are metered per request, so a workload without constant load pays nothing between queries. The operational surface is the table you were already running, and the write path is the one you already know.
Links
- Amazon DynamoDB now supports real-time vector search at any scale: the GA announcement, 5 August 2026
- Using vector indexes in DynamoDB: distance functions, SearchSchema, projections, and feature interactions
- Data synchronization between tables and vector indexes: backfill behaviour and the asynchronous indexing guarantee
- Monitoring vector index capacity: the byte-based metering units and what drives search cost
- Best practices for vector indexes: partition key cardinality, projection width, and keeping embeddings in sync
- Related posts: idempotency with DynamoDB conditional writes and Lambda’s scaling limits