DynamoDB-Vektorsuche
DynamoDB hat am 5. August 2026 native Vektorsuche bekommen. Du speicherst Embeddings als gewöhnliche List von Number-Werten auf deinen Items, fügst einen Vektorindex hinzu und fährst Approximate-Nearest-Neighbor-Queries mit der neuen SearchVectors-API.
Bis jetzt hieß Similarity Search: die Tabelle nach OpenSearch oder in eine separate Vektordatenbank replizieren und beide synchron halten. Diese Pipeline ist weg. Das Billing-Modell, das sie ersetzt, gleicht nichts anderem in DynamoDB.
Unterstützt DynamoDB Vektorsuche?
Ja — nativ, seit dem 5. August 2026. Du speicherst Embeddings als gewöhnliche
List von Number-Werten, fügst einen Vektorindex hinzu und fährst
Approximate-Nearest-Neighbor-Queries mit der SearchVectors-API — kein
OpenSearch-Replikat, keine separate Vektordatenbank. Es funktioniert nur auf
On-Demand-Tabellen, bis zu 4,096 Dimensionen, und wird pro geschriebenem,
durchsuchtem und gespeichertem Byte abgerechnet.
- Eine dritte Index-Familie: Vektorindizes stehen neben und LSIs. Eine neue Read-API (
SearchVectors), nur ANN, nur On-Demand-Tabellen, bis zu 4,096 Dimensionen. - Sie ist schnell, gemessen: gegen unseren live laufenden 1024-dim Index in us-east-1 antwortete
SearchVectorsso schnell wieGetItemvom selben Client (p50 39 ms vs. 44 ms), und ein frischer Write wurde in ~136 ms suchbar. - Gemetert wird pro Byte: $0.52 pro GB Vektor-Writes, $0.002 pro GB Vektordaten, die eine Suche untersucht, $0.25 pro GB-Monat Storage (us-east-1). Ein Embedding zu indexieren lässt seine Basistabellen-Kopie mit exakt 4 Bytes pro Dimension abrechnen; dieselbe Liste unindexiert rechnet ~1.9× ab.
- S3 Vectors bleibt der Bulk-Store: grob 8× günstiger at rest und weit günstiger beim Batch-Load. DynamoDB gewinnt bei Millisekunden-Reads, Streaming-Writes und Vektoren, die direkt neben dem Item leben, das sie beschreiben.
Wie ein Vektorindex funktioniert
Es gibt keinen neuen Attribut-Typ. Ein Embedding ist eine gewöhnliche Liste von Zahlen auf dem Item, {"L": [{"N": "0.0132"}, {"N": "-0.0475"}, …]} auf dem Wire, geschrieben mit denselben PutItem und UpdateItem, die du schon benutzt.
Der Index ist eine separate Struktur. DynamoDB repliziert den Vektor asynchron mit 32-Bit-Float-Präzision hinein, zusammen mit allen Attributen, die du projizierst oder auf die du filterst. Suchergebnisse sind eventually consistent, wie ein -Read.
Der Lag ist in der Praxis klein. Gegen unseren Live-Testindex tauchte ein frisch geschriebener Vektor rund 136 ms nach der Rückkehr des PutItem in den Suchergebnissen auf. Baue trotzdem nie einen Read-your-own-write-Flow darauf.
Wo er neben den Index-Typen steht, die du kennst:
| Vektorindex | GSI | LSI | |
|---|---|---|---|
| Max. pro Tabelle | 5 | 20 | 5 |
| Read-API | SearchVectors | Query, Scan | Query, Scan |
| PartiQL | Nein | Ja | Ja |
| Capacity-Modus | Nur On-Demand | Beide | Beide |
| Konsistenz | Eventual | Eventual | Strong verfügbar |
| Nach Table Creation anlegbar | Ja | Ja | Nein |
Jeder Index fixiert bei der Erstellung seine Dimensionsanzahl (bis zu 4,096) und eine von drei Distanzfunktionen. COSINE und EUCLIDEAN scoren niedriger-ist-ähnlicher; DOT_PRODUCT scort höher-ist-ähnlicher und kann negativ werden. Nichts davon lässt sich später ändern.
Eine Präzisions-Anmerkung, bevor du irgendetwas benchmarkst. Der Index hält Vektoren als f32; Werte mit höherer Präzision werden akzeptiert, verlieren aber auf dem Weg hinein Präzision. Kommst du mit float64-Embeddings an, wird jede Distanz gegen die f32-Kopie berechnet — miss Recall also gegen f32, nicht gegen deine Originale.
Einen Index anlegen und durchsuchen
Angenommen, du fährst semantische Suche über Support-Tickets, damit ein Agent „Kunden, die genau das schon einmal hatten“ findet, ohne Keywords zu matchen. Jedes Ticket-Item trägt ein Embedding aus Subject und Body, generiert von einem Modell deiner Wahl (Titan Text Embeddings V2 kostet $0.02 pro Million Input-Tokens auf Bedrock).
Füge den Index zur bestehenden Tabelle hinzu. Das HASH-Element scoped jede Suche auf einen product-Wert; INLINE_FILTER-Attribute (bis zu 18) erlauben Equality-Filter zur Suchzeit:
aws dynamodb update-table \
--table-name SupportTickets \
--attribute-definitions AttributeName=product,AttributeType=S \
AttributeName=severity,AttributeType=S \
--vector-index-updates '[{"Create": {
"IndexName": "TicketEmbeddings",
"VectorAttribute": {"AttributeName": "embedding"},
"SearchSchema": [
{"AttributeName": "product", "SearchSchemaElementType": "HASH"},
{"AttributeName": "severity", "SearchSchemaElementType": "INLINE_FILTER"}
],
"Projection": {"ProjectionType": "KEYS_ONLY"},
"Dimensions": 1024,
"DistanceFunction": "COSINE"
}}]'Der Build verhält sich wie ein GSI-Backfill mit schärferen Kanten. SearchVectors liefert während des gesamten Builds ValidationException, ohne Partial Results.
AWS warnt, dass der Such-Endpoint noch eine Weile rejecten kann, selbst nachdem DescribeTable ACTIVE sagt. Es gibt keinen Waiter; probe mit einer echten Suche in einem Retry-Loop. Als wir den Index zusammen mit einer leeren Tabelle angelegt haben, ging er in 26 Sekunden auf ACTIVE und akzeptierte Suchen 0.6 s später.
Die Suche nimmt das Query-Embedding als nacktes JSON-Array von {"N": …}-Werten. Wickle es nicht in ein DynamoDB-L. Das gespeicherte Attribut nutzt den List-Typ, der Request-Parameter nicht, und beides zu verwechseln ist ein leichter erster Fehler:
aws dynamodb search-vectors \
--table-name SupportTickets \
--index-name TicketEmbeddings \
--search-vector file://query-embedding.json \
--top-k 5 \
--search-condition-expression "product = :p AND severity = :sev" \
--expression-attribute-values '{":p": {"S": "checkout"}, ":sev": {"S": "high"}}'Zurück kommen bis zu TopK Items, sortiert ähnlichste-zuerst, jedes mit einem Score, plus ConsumedCapacity, wenn du danach fragst. TopK cappt bei 100, es gibt keine Pagination, und die Response cappt bei 16 MB.
Das Embedding selbst ist aus den Ergebnissen ausgeschlossen, außer du projizierst es und fragst es an. Dieser Default ist Absicht; Vektoren zurückzugeben bläht sowohl die Response als auch die Such-Rechnung auf.
Filter Expressions akzeptieren nur Equality, ohne BETWEEN, IN oder begins_with. Definiert der Index ein HASH-Attribut, muss jede Suche genau einen Wert dafür pinnen. AWSs Formulierung zu Range-Operatoren ist "not yet available", das kann sich also noch lockern.
Zwei operative Überraschungen solltest du vor dem ersten Deploy kennen. SearchVectors braucht die neue IAM-Action dynamodb:SearchVectors, die keine deiner bestehenden Read-Policies enthält.
Sie spricht außerdem mit einem separaten Endpoint, search-dynamodb.{region}.amazonaws.com. Egress-Allowlists und VPC-Endpoint-Configs, die nur dynamodb.{region} abdecken, brechen allein die Vektorsuche — mit einem Connection Error, der nie sagt, warum.
Was ein Vektorindex abrechnet
Drei neue Meter, alle pro Byte, mit einem 1-KB-Minimum pro Write und pro Such-Request, zusätzlich zu den normalen Tabellen-Charges (us-east-1, aus der AWS Pricing API, 2026-08-15):
| Meter | Standard | Standard-IA |
|---|---|---|
| Vektor-Writes | $0.52/GB | $0.65/GB |
| Untersuchte Vektordaten pro Suche | $0.002/GB | $0.0025/GB |
| Storage (Tabelle und Index) | $0.25/GB-mo | $0.10/GB-mo |
Die Docs warnen, dass die Basistabellen-Kopie eines Embeddings, gespeichert als Dezimal-Strings in einer List, "considerably larger" sein könne als die f32-Kopie im Index. Wir haben das Write-Unit-Billing gegen live laufende Tabellen in us-east-1 gemessen, und die Wahrheit ist seltsamer.
Ein Embedding auf einem Attribut ohne Vektorindex rechnet nach der dokumentierten Dezimal-Regel ab, grob 1.9× der f32-Größe. Richte einen Vektorindex auf dasselbe Attribut und sein Basistabellen-Billing fällt auf exakt 4 Bytes pro Dimension:
| Dimensionen | Unindexiertes List-Attribut (abgerechnet) | Dasselbe Attribut, vektorindexiert (abgerechnet) |
|---|---|---|
| 256 | 1,914 B | 1,024 B |
| 768 | 5,760 B | 3,072 B |
| 1,024 | 7,653 B | 4,096 B |
| 1,536 | 11,501 B | 6,144 B |
| 3,072 | 22,957 B | 12,288 B |
Gemessen per Binärsuche über die Write-Unit-Grenze mit einem Padding-Attribut, frischem Item-Key pro Write, aufs Byte kalibriert. Unser volles 1024-dim Ticket-Item rechnete 5 Write Units ab; das identische Item ohne Index auf embedding rechnet 8 ab.
Der Vektor-Write-Meter folgte in denselben Läufen eng der f32-Größe. VectorWriteRequestBytes kam als 4 Bytes pro Dimension plus 11 B Key-Overhead auf einem nackten Index zurück, und plus 65 B mit unserem Zwei-Attribut-Search-Schema.
Das Such-Billing ist der Meter, den du nicht im Voraus berechnen kannst. VectorSearchRequestBytes trackt, wie viel Vektordaten die ANN-Traversierung untersucht hat, und AWSs eigene Guidance ist, es über ReturnConsumedCapacity zu messen, statt es aus der Dimensionsanzahl zu schätzen.
Unsere Probe liefert die ersten Datenpunkte. TopK=10 über eine 50-Vektor-Partition untersuchte 22.2-22.4 KB pro Suche; dieselbe Suche über eine 1-Vektor-Partition untersuchte immer noch 21.4 KB — bei kleiner Skala gibt es also einen Floor von grob 21 KB (etwa $0.00000004) pro Query. AWSs Tutorial berichtet 31,449 Bytes für sein eigenes 50-Vektor-Beispiel.
Modelliere die tabellenseitigen Kosten im Pricing Calculator; die Vektor-Meter stapeln sich auf die Write Units, die er bereits berechnet.
DynamoDB-Vektorsuche vs. S3 Vectors
AWS verkauft jetzt zwei serverlose Vector Stores, und sie sind für entgegengesetzte Access Patterns gebaut. S3 Vectors (GA Dezember 2025) hält bis zu 2 Milliarden Vektoren pro Index bei $0.06/GB-Monat, antwortet im Bereich von 100 ms bis 1 s und rechnet jede Query gegen die Größe des ganzen Index ab.
DynamoDB antwortet in Millisekunden und rechnet gegen das ab, was die Suche untersucht — nicht gegen das, was der Index hält.
| DynamoDB-Vektorsuche | S3 Vectors | |
|---|---|---|
| GA | Aug 2026 | Dez 2025 |
| Latenzklasse | Einstellige ms (AWS-Angabe) | ~100 ms häufig, unter 1 s selten (AWS-Angabe) |
| Skalierungsgrenze | Kein genanntes Vektor-Cap; 600-GB-Tabellen-Cap für Index-Erstellung (soft) | 2 Mrd. Vektoren pro Index |
| Max. Dimensionen | 4,096 | 4,096 |
| Distanzfunktionen | Cosine, Euclidean, Dot Product | Cosine, Euclidean |
| Index-Writes | Asynchron aus der Tabelle (eventually consistent) | Strongly consistent |
| Filterung | Nur Equality, ≤18 Attribute + 1 Partition Key | Umfangreiche Metadaten-Filter, 2-KB-Filterable-Cap pro Vektor |
| TopK | 100, keine Pagination | 10,000, paginiert |
| Storage | $0.25/GB-mo, zweimal (Tabelle + Index) | $0.06/GB-mo, einmal |
| Writes | $0.52/GB, 1 KB Min./Request | $0.20/GB, 128 KB Min./PUT |
| Queries | $0.002/GB untersucht | $2.50/M Requests + Processed-Bytes-Charge über den ganzen Index |
Die Write-Minimums entscheiden den Streaming-Fall, und sie zeigen in die entgegengesetzte Richtung der Storage-Raten. Einen 1024-dim Vektor einzeln geschrieben, pro Million Writes (aus den verifizierten Raten und unseren gemessenen 5 Write Units + 4,161 Vektor-Write-Bytes pro Item):
| Write-Pattern | DynamoDB | S3 Vectors |
|---|---|---|
| Einzelne Vektor-Writes | ~$5.14/M | ~$24.41/M |
Gebatcht (500 pro PutVectors) | n/a (Writes sind per Item) | ~$0.78/M |
S3s 128-KB-Minimum pro PUT macht es zur teuren Option für genau den Workload, für den die Leute es für günstig halten. Streame Vektoren einzeln nach S3 Vectors und du zahlst fast 5× DynamoDBs Rate; lade sie gebatcht und du zahlst grob 7× weniger.
Monatliche Storage- und Query-Summen für einen 1024-dim Korpus bei 1M Queries pro Monat, berechnet aus den verifizierten Raten (Write-Kosten sind die Pro-Million-Tabelle oben). S3 Vectors' Query-Charge folgt seiner publizierten Formel: ganze Index-Größe mal eine gestaffelte Rate.
DynamoDBs Query-Charge hängt von den untersuchten Bytes ab, also zeigen wir eine Sensitivitäts-Range, statt so zu tun, als kennten wir deine Traversierung:
| Korpus | DynamoDB-Storage | DynamoDB-Queries (4 / 40 / 400 MB untersucht) | S3 Vectors Storage | S3 Vectors Queries |
|---|---|---|---|---|
| 1M Vektoren | ~$1.95 | $8 / $80 / $800 | ~$0.23 | ~$11 |
| 10M Vektoren | ~$19.50 | $8 / $80 / $800 | ~$2.35 | ~$80 |
| 100M Vektoren | ~$195 | $8 / $80 / $800 | ~$23.50 | ~$217 |
Zwei Dinge fallen aus dieser Tabelle heraus. DynamoDBs Kosten pro Query wachsen nicht mit der Korpusgröße — eine ANN-Suche untersucht eine Nachbarschaft, nicht den Index, und Partition-Key-Scoping schrumpft sie weiter.
S3 Vectors' Storage-Vorteil (~8×, weil DynamoDB zwei f32-Kopien zur 4×-Rate speichert) verzinst sich für immer, ob jemand queryt oder nicht.
Wann welche Option passt
- Vektoren beschreiben lebende Items, die du schon in DynamoDB hältst (Tickets, Produkte, User-Sessions, Agent-Memory): nimm den Vektorindex. Ein Write-Pfad, ein Item, keine Sync-Pipeline, die driften kann.
- Millionen Embeddings, gelegentlich gequeryt (RAG über Dokumente, Archive, Nightly Jobs): nimm S3 Vectors. Günstig batch-loaden, $0.06/GB at rest zahlen, ein paar hundert ms tolerieren.
- Hohe QPS mit Hybrid-Ranking (Text-Relevanz + Vektoren, Faceting, Aggregationen): OpenSearch bleibt die Antwort, mit einem Infrastruktur-Floor von grob $350/Monat für eine klassische Serverless Collection.
- Vektoren gejoint mit relationalen Daten: Aurora PostgreSQL mit pgvector, das auf null skaliert und für kleine RAG-Workloads unter ~$50/Monat landet.
Der ehrliche Default für einen DynamoDB-Shop ist beides. Halte heiße, filterbare Vektoren auf der Tabelle, wo Writes atomar mit dem Item sind, und archiviere den Long Tail nach S3 Vectors, dessen strongly consistent gebatchte Writes es zu einem sauberen Sink machen.
Die Fallstricke
- Stilles De-Indexing: ein Item, dem das
HASH-Attribut des Index fehlt, schreibt problemlos in die Tabelle und betritt den Vektorindex nie. Wir haben es live reproduziert: dasPutItemwar erfolgreich, und der Vektor fehlte 15 Sekunden später in jeder Partition. Kein Error, kein Ergebnis, nichts in der Response, das es dir sagt. - Writes mit falscher Dimension werden rejected: wechsle das Embedding-Modell ohne Migration und jeder Write failt mit einer
ValidationException, die das Attribut und beide Größen nennt (Invalid size for parameter, wortwörtlich auf ihrer eigenen Seite festgehalten), weil der Index die Dimensionsanzahl für immer pinnt. - Stale Embeddings: DynamoDB berechnet Vektoren nie neu. Editiere den Text eines Tickets, ohne
embeddingneu zu schreiben, und Suchen matchen still den alten Content. Streams plus ein Regenerations-Consumer ist der Standard-Fix. TopKgibt immer K Items zurück: mit drei guten Matches und--top-k 10bekommst du trotzdem 10. Beurteile Relevanz über denScore, nicht über die Ergebnisanzahl, und denk daran, dass die Score-Richtung zwischen den Distanzfunktionen flippt.- Die 1-KB-Minimums: Vektoren mit niedriger Dimension metern nicht proportional günstiger, weder bei Writes noch bei Suchen.
- Alles ist immutable: Dimensionen, Distanzfunktion und das Attribut-Set einer
INCLUDE-Projection erfordern alle Delete-and-Recreate, um sich zu ändern. Index-Storage rechnet über die ganze Lebensdauer des Index ab, gequeryt oder nicht.
An deinen eigenen Tabellen ausprobieren
Die Vektorsuche erbt die Kostendisziplin, die dir der Rest von DynamoDB beigebracht hat. Dimensioniere das Embedding, bevor du dich darauf festlegst, denn Item-Size-Limits gelten weiter, und ein 3072-dim Embedding legt 12 KB auf jeden Item-Write — auf beiden Metern.
Die Index-Mechanik fühlt sich vertraut an, wenn du weißt, wie GSIs asynchron replizieren und wann ein GSI statt eines LSI passt. Für lexikalische Suche über dieselben Daten gilt: DynamoDB hat weiterhin keine Volltext-Engine; Vektorsuche matcht Bedeutung statt Schreibweise.
Prüfe die echten Byte-Kosten eines Embeddings im Item Size Calculator, dann probiere DynoTable aus, um die Items hinter deinem Vektorindex zu browsen — Embeddings rendern als gewöhnliche List-Attribute direkt neben den Feldern, auf die du filterst.