{
    "componentChunkName": "component---src-templates-mdx-content-page-js",
    "path": "/dynamodb-vector-search/",
    "result": {"data":{"mdx":{"body":"var _excluded = [\"components\"];\n\nfunction _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }\n\nfunction _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }\n\nfunction _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }\n\n/* @jsxRuntime classic */\n\n/* @jsx mdx */\nvar _frontmatter = {\n  \"path\": \"/dynamodb-vector-search/\",\n  \"publishedDate\": \"2026-10-23\",\n  \"updatedDate\": \"2026-10-23\",\n  \"metaTitle\": \"DynamoDB Vector Search: API, Examples and Pricing\",\n  \"metaDescription\": \"Build DynamoDB vector search with native indexes, Bedrock embeddings and SearchVectors. Includes SDK examples, quotas, pricing and database comparisons.\",\n  \"title\": \"DynamoDB vector search: indexes, examples, pricing and limits\",\n  \"authorName\": \"Rafal Wilinski\",\n  \"authorLink\": \"https://x.com/rafalwilinski\",\n  \"authorImage\": \"/images/authors/rafal-wilinski.jpg\",\n  \"image\": \"/images/posts/dynamodb-vector-search/social.png\"\n};\nvar layoutProps = {\n  _frontmatter: _frontmatter\n};\nvar MDXLayout = \"wrapper\";\nreturn function MDXContent(_ref) {\n  var components = _ref.components,\n      props = _objectWithoutProperties(_ref, _excluded);\n\n  return mdx(MDXLayout, _extends({}, layoutProps, props, {\n    components: components,\n    mdxType: \"MDXLayout\"\n  }), mdx(\"p\", null, \"Amazon DynamoDB supports native vector search through vector indexes and the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"SearchVectors\"), \" API, generally available since August 5, 2026. Store embeddings alongside your items, create an index on an on-demand table, and retrieve approximate nearest neighbors without copying the data to a separate vector database. Indexes support up to 4,096 dimensions and return up to 100 matches per search; search results are eventually consistent. AWS's \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://aws.amazon.com/about-aws/whats-new/2026/08/amazon-dynamodb-vector-search/\"\n  }, \"launch announcement\"), \" describes single-digit millisecond latency at 99%+ recall, which is a service performance claim, not a measurement of your application's complete retrieval path.\"), mdx(\"h2\", null, \"How does DynamoDB vector search work?\"), mdx(\"p\", null, \"An embedding model converts content into a numerical vector. Related content should occupy nearby positions in that model's vector space. DynamoDB stores the embedding in an item and maintains a separate index for approximate nearest neighbor (ANN) retrieval. Your application embeds the query with the same model, submits the query vector, and receives ranked items.\"), mdx(\"p\", null, \"The word \", mdx(\"strong\", {\n    parentName: \"p\"\n  }, \"approximate\"), \" matters: the engine can miss a true nearest neighbor. Recall measures how many relevant nearest neighbors are recovered against an exact-search reference. Retrieval quality also depends on your embedding model, chunk boundaries and filters. Measure relevance on representative queries, including queries with no useful answer; a low distance does not prove that a passage answers a question.\"), mdx(\"p\", null, mdx(\"img\", {\n    parentName: \"p\",\n    \"src\": \"/images/posts/dynamodb-vector-search/vector-request-flow.svg\",\n    \"alt\": \"Bedrock embeds content and queries; DynamoDB synchronizes stored vectors into an index that returns ranked matches through SearchVectors.\"\n  })), mdx(\"p\", null, \"Embedding generation is your application's responsibility. Index synchronization does not regenerate an embedding when its source text changes. Write the new content and its corresponding embedding together, or use a version-checked background workflow. \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"/dynamodb-streams/\"\n  }, \"DynamoDB Streams\"), \" can trigger that workflow, but native index synchronization itself needs no custom stream consumer.\"), mdx(\"h2\", null, \"What is a DynamoDB vector index?\"), mdx(\"p\", null, \"A vector index is a distinct index type. A \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"/dynamodb-gsi/\"\n  }, \"global secondary index\"), \" supports key-based retrieval; a vector index ranks similarity. Keep ordinary \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"/dynamodb-indexes/\"\n  }, \"DynamoDB indexes\"), \" for exact IDs, ordered access patterns and range queries.\"), mdx(\"p\", null, \"The \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_VectorIndex.html\"\n  }, \"VectorIndex API configuration\"), \" uses these names:\"), mdx(\"table\", null, mdx(\"thead\", {\n    parentName: \"table\"\n  }, mdx(\"tr\", {\n    parentName: \"thead\"\n  }, mdx(\"th\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Setting\"), mdx(\"th\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Meaning\"))), mdx(\"tbody\", {\n    parentName: \"table\"\n  }, mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, mdx(\"inlineCode\", {\n    parentName: \"td\"\n  }, \"IndexName\")), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Name used in \", mdx(\"inlineCode\", {\n    parentName: \"td\"\n  }, \"SearchVectors\"))), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, mdx(\"inlineCode\", {\n    parentName: \"td\"\n  }, \"VectorAttribute.AttributeName\")), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Top-level item attribute containing the embedding\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, mdx(\"inlineCode\", {\n    parentName: \"td\"\n  }, \"Dimensions\")), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Number of elements in every indexed vector\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, mdx(\"inlineCode\", {\n    parentName: \"td\"\n  }, \"DistanceFunction\")), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, mdx(\"inlineCode\", {\n    parentName: \"td\"\n  }, \"COSINE\"), \", \", mdx(\"inlineCode\", {\n    parentName: \"td\"\n  }, \"EUCLIDEAN\"), \" or \", mdx(\"inlineCode\", {\n    parentName: \"td\"\n  }, \"DOT_PRODUCT\"))), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, mdx(\"inlineCode\", {\n    parentName: \"td\"\n  }, \"SearchSchema\")), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Optional routing key and inline filter definitions\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, mdx(\"inlineCode\", {\n    parentName: \"td\"\n  }, \"Projection\")), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, mdx(\"inlineCode\", {\n    parentName: \"td\"\n  }, \"ProjectionType\"), \" of \", mdx(\"inlineCode\", {\n    parentName: \"td\"\n  }, \"KEYS_ONLY\"), \", \", mdx(\"inlineCode\", {\n    parentName: \"td\"\n  }, \"INCLUDE\"), \" or \", mdx(\"inlineCode\", {\n    parentName: \"td\"\n  }, \"ALL\"), \"; \", mdx(\"inlineCode\", {\n    parentName: \"td\"\n  }, \"NonKeyAttributes\"), \" names the extra fields for \", mdx(\"inlineCode\", {\n    parentName: \"td\"\n  }, \"INCLUDE\"))))), mdx(\"p\", null, \"Store the vector as a DynamoDB \", mdx(\"strong\", {\n    parentName: \"p\"\n  }, \"List of Numbers\"), \", an \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"L\"), \" containing \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"N\"), \" values. It is not a Number Set, binary blob or scalar \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"AttributeDefinitions\"), \" entry. The index converts coordinates to 32-bit floating point; the base table retains the values you wrote. Higher precision in the table does not produce higher precision in search.\"), mdx(\"p\", null, \"Each \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_SearchSchemaElement.html\"\n  }, \"SearchSchemaElement\"), \" has \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"AttributeName\"), \" and \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"SearchSchemaElementType\"), \":\"), mdx(\"ul\", null, mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"HASH\"), \" routes a search to one partition-key value, such as a tenant or catalog. It need not be the base table's partition key. If configured, its equality condition is required on every search.\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"INLINE_FILTER\"), \" permits additional equality filters within that search. These constraints are optional at query time and are applied during index traversal.\")), mdx(\"p\", null, \"Declare every search-schema attribute in the table's \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"AttributeDefinitions\"), \", including inline filters. Declare projected text fields only in the projection, not in \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"AttributeDefinitions\"), \". An index without a \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"HASH\"), \" searches across the index and cannot distribute traffic by independently routed key values.\"), mdx(\"p\", null, \"Projection controls which item attributes are copied into the index. The vector and required index data are retained even with \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"KEYS_ONLY\"), \"; \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"INCLUDE\"), \" adds selected fields and \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"ALL\"), \" copies the full item. \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"SearchVectors\"), \" cannot fetch an unprojected field from the base table. A smaller projection reduces index storage, replication work and returned data; fetch additional attributes separately when needed. AWS details this in \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/VectorSearchStorage.html\"\n  }, \"vector storage considerations\"), \".\"), mdx(\"p\", null, \"Vector indexes require \", mdx(\"strong\", {\n    parentName: \"p\"\n  }, mdx(\"inlineCode\", {\n    parentName: \"strong\"\n  }, \"PAY_PER_REQUEST\"), \" on the base table\"), \". Standard and Standard-IA table classes are supported. If your existing table is provisioned, account for the change to \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"/dynamodb-on-demand-vs-provisioned-scaling/\"\n  }, \"on-demand pricing and scaling\"), \" before enabling this feature.\"), mdx(\"h3\", null, \"Which distance metric should you use?\"), mdx(\"table\", null, mdx(\"thead\", {\n    parentName: \"table\"\n  }, mdx(\"tr\", {\n    parentName: \"thead\"\n  }, mdx(\"th\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, mdx(\"inlineCode\", {\n    parentName: \"th\"\n  }, \"DistanceFunction\")), mdx(\"th\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Meaning of \", mdx(\"inlineCode\", {\n    parentName: \"th\"\n  }, \"Score\")), mdx(\"th\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Better match\"))), mdx(\"tbody\", {\n    parentName: \"table\"\n  }, mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, mdx(\"inlineCode\", {\n    parentName: \"td\"\n  }, \"COSINE\")), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"One minus cosine similarity; compares direction, ignoring length; scores range from 0 to 2\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Lower\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, mdx(\"inlineCode\", {\n    parentName: \"td\"\n  }, \"EUCLIDEAN\")), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Straight-line distance between vectors\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Lower\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, mdx(\"inlineCode\", {\n    parentName: \"td\"\n  }, \"DOT_PRODUCT\")), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Dot product; sensitive to both direction and magnitude\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Higher\")))), mdx(\"p\", null, \"The \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/VectorSearch.html\"\n  }, \"distance-function documentation\"), \" recommends matching the metric to the embedding model. Normalized vectors have equivalent cosine and dot-product rankings. Do not sort every metric ascending, and do not label every score a probability.\"), mdx(\"p\", null, mdx(\"img\", {\n    parentName: \"p\",\n    \"src\": \"/images/posts/dynamodb-vector-search/vector-nearest-neighbors.svg\",\n    \"alt\": \"In a two-dimensional Euclidean example, A, B and C are the three closest points to query Q; cosine distance instead compares directions from the origin.\"\n  })), mdx(\"p\", null, \"The diagram uses invented coordinates to explain distance, not a projection of real embeddings. Changing dimensions or the distance function requires a new index. For a model migration, populate a different embedding attribute and index, compare relevance, then switch searches. Two models with the same dimension count still occupy different vector spaces.\"), mdx(\"h2\", null, \"SearchVectors request and response reference\"), mdx(\"p\", null, \"These are all nine request parameters in the current \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_SearchVectors.html\"\n  }, \"SearchVectors API\"), \":\"), mdx(\"table\", null, mdx(\"thead\", {\n    parentName: \"table\"\n  }, mdx(\"tr\", {\n    parentName: \"thead\"\n  }, mdx(\"th\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Parameter\"), mdx(\"th\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Required?\"), mdx(\"th\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Value\"))), mdx(\"tbody\", {\n    parentName: \"table\"\n  }, mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, mdx(\"inlineCode\", {\n    parentName: \"td\"\n  }, \"TableName\")), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Yes\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Table name or ARN\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, mdx(\"inlineCode\", {\n    parentName: \"td\"\n  }, \"IndexName\")), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Yes\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Active vector index name\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, mdx(\"inlineCode\", {\n    parentName: \"td\"\n  }, \"SearchVector\")), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Yes\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Array of DynamoDB number values, matching index dimensions\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, mdx(\"inlineCode\", {\n    parentName: \"td\"\n  }, \"TopK\")), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Yes\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Integer from 1 to 100\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, mdx(\"inlineCode\", {\n    parentName: \"td\"\n  }, \"SearchConditionExpression\")), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"When \", mdx(\"inlineCode\", {\n    parentName: \"td\"\n  }, \"HASH\"), \" exists\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Routing-key equality and optional inline-filter equalities\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, mdx(\"inlineCode\", {\n    parentName: \"td\"\n  }, \"ExpressionAttributeNames\")), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"As needed\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Attribute aliases such as \", mdx(\"inlineCode\", {\n    parentName: \"td\"\n  }, \"#lang\"))), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, mdx(\"inlineCode\", {\n    parentName: \"td\"\n  }, \"ExpressionAttributeValues\")), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"As needed\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Typed values such as \", mdx(\"inlineCode\", {\n    parentName: \"td\"\n  }, \"\\\":lang\\\": { \\\"S\\\": \\\"en\\\" }\"))), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, mdx(\"inlineCode\", {\n    parentName: \"td\"\n  }, \"ProjectionExpression\")), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"No\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Comma-separated attributes already projected into the index\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, mdx(\"inlineCode\", {\n    parentName: \"td\"\n  }, \"ReturnConsumedCapacity\")), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"No\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, mdx(\"inlineCode\", {\n    parentName: \"td\"\n  }, \"NONE\"), \", \", mdx(\"inlineCode\", {\n    parentName: \"td\"\n  }, \"TOTAL\"), \" or \", mdx(\"inlineCode\", {\n    parentName: \"td\"\n  }, \"INDEXES\"))))), mdx(\"p\", null, \"With the low-level SDK, \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"SearchVector\"), \" is an array such as \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"[{ N: \\\"0.2\\\" }, { N: \\\"0.8\\\" }]\"), \". It has \", mdx(\"strong\", {\n    parentName: \"p\"\n  }, \"no outer \", mdx(\"inlineCode\", {\n    parentName: \"strong\"\n  }, \"L\"), \" wrapper\"), \". The item attribute used in a write does have that wrapper. The full example below generates all required coordinates rather than using an abbreviated vector.\"), mdx(\"p\", null, \"Filtering uses \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"SearchConditionExpression\"), \", not \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"FilterExpression\"), \". Current API and developer-guide documentation support equality on top-level \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"HASH\"), \" and \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"INLINE_FILTER\"), \" attributes. Do not copy range conditions, \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"IN\"), \" or nested document paths from ordinary Query examples.\"), mdx(\"p\", null, \"The response has \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"SearchResults\"), \", an ordered array of \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_SearchResultItem.html\"\n  }, \"SearchResultItem\"), \" objects. Each contains \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"Item\"), \", a DynamoDB attribute map, and numeric \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"Score\"), \". When requested, \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"ConsumedCapacity.VectorSearchRequestBytes\"), \" reports search consumption. There is no \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"LastEvaluatedKey\"), \", \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"NextToken\"), \" or \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"ConsistentRead\"), \" option.\"), mdx(\"p\", null, \"The working guide says returned items omit the vector attribute by default; request it explicitly in \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"ProjectionExpression\"), \" if needed. Keep it out of normal RAG results to avoid returning hundreds of coordinates alongside each passage.\"), mdx(\"h3\", null, \"Use the dedicated search endpoint\"), mdx(\"p\", null, mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"SearchVectors\"), \" uses a different endpoint from table creation and writes. Current SDKs and AWS CLI v2 route the operation automatically. Custom HTTP clients can use \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"search-dynamodb.<region>.api.aws\"), \" for dual-stack access or the account-based \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"<account-id>.search-ddb.<region>.amazonaws.com\"), \". The \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/VectorSearchWorkingWith.html\"\n  }, \"endpoint and operation guide\"), \" documents both. Do not force the regular table endpoint onto a search client.\"), mdx(\"h2\", null, \"End-to-end example: Bedrock embeddings, writes and filtered search\"), mdx(\"p\", null, \"This example builds a small tenant-scoped documentation search. It uses table \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"VectorDocuments\"), \", index \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"ByMeaning\"), \", embedding attribute \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"embedding\"), \", routing key \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"tenantId\"), \", and inline filter \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"language\"), \" throughout. The snippets target AWS, require appropriate credentials and incur service charges when run there.\"), mdx(\"p\", null, mdx(\"strong\", {\n    parentName: \"p\"\n  }, \"Verification boundary:\"), \" the TypeScript was type-checked against AWS SDK v3 and the Python requests validated against botocore's service model. Table writes and reads ran on DynamoDB Local with synthetic embedding fixtures. Bedrock inference and real vector search were not executed against AWS. DynamoDB Local does not implement \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"SearchVectors\"), \", so no ranking or latency output below is presented as a cloud test.\"), mdx(\"h3\", null, \"1. Create the table and vector index\"), mdx(\"p\", null, \"Use a current AWS CLI v2, Node.js 22 or later, and these packages in a new example directory:\"), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-bash\"\n  }, \"npm init -y\\nnpm install @aws-sdk/client-dynamodb @aws-sdk/lib-dynamodb @aws-sdk/client-bedrock-runtime tsx\\n\")), mdx(\"p\", null, \"Save this as \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"table.json\"), \". Amazon Titan Text Embeddings V2 supports \", mdx(\"strong\", {\n    parentName: \"p\"\n  }, \"1,024 dimensions by default, or 512 or 256\"), \". We explicitly choose 256 for both the index and model requests. AWS recommends splitting documents into logical segments for retrieval rather than embedding an entire long document; see the \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://docs.aws.amazon.com/bedrock/latest/userguide/titan-embedding-models.html\"\n  }, \"Titan model documentation\"), \".\"), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-json\"\n  }, \"{\\n  \\\"TableName\\\": \\\"VectorDocuments\\\",\\n  \\\"BillingMode\\\": \\\"PAY_PER_REQUEST\\\",\\n  \\\"AttributeDefinitions\\\": [\\n    { \\\"AttributeName\\\": \\\"id\\\", \\\"AttributeType\\\": \\\"S\\\" },\\n    { \\\"AttributeName\\\": \\\"tenantId\\\", \\\"AttributeType\\\": \\\"S\\\" },\\n    { \\\"AttributeName\\\": \\\"language\\\", \\\"AttributeType\\\": \\\"S\\\" }\\n  ],\\n  \\\"KeySchema\\\": [{ \\\"AttributeName\\\": \\\"id\\\", \\\"KeyType\\\": \\\"HASH\\\" }],\\n  \\\"VectorIndexes\\\": [{\\n    \\\"IndexName\\\": \\\"ByMeaning\\\",\\n    \\\"VectorAttribute\\\": { \\\"AttributeName\\\": \\\"embedding\\\" },\\n    \\\"Dimensions\\\": 256,\\n    \\\"DistanceFunction\\\": \\\"COSINE\\\",\\n    \\\"SearchSchema\\\": [\\n      { \\\"AttributeName\\\": \\\"tenantId\\\", \\\"SearchSchemaElementType\\\": \\\"HASH\\\" },\\n      { \\\"AttributeName\\\": \\\"language\\\", \\\"SearchSchemaElementType\\\": \\\"INLINE_FILTER\\\" }\\n    ],\\n    \\\"Projection\\\": {\\n      \\\"ProjectionType\\\": \\\"INCLUDE\\\",\\n      \\\"NonKeyAttributes\\\": [\\\"title\\\", \\\"text\\\"]\\n    }\\n  }]\\n}\\n\")), mdx(\"p\", null, \"Create it once, with either the CLI or the SDK alternative:\"), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-bash\"\n  }, \"aws dynamodb create-table --region us-east-1 --cli-input-json file://table.json\\naws dynamodb wait table-exists --region us-east-1 --table-name VectorDocuments\\n\")), mdx(\"p\", null, \"For SDK v3, save \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"create.mts\"), \" and run \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"npx tsx create.mts\"), \" instead of the two CLI commands:\"), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-ts\"\n  }, \"import { readFile } from \\\"node:fs/promises\\\"\\nimport {\\n  CreateTableCommand, DynamoDBClient, waitUntilTableExists,\\n  type CreateTableCommandInput,\\n} from \\\"@aws-sdk/client-dynamodb\\\"\\n\\nconst client = new DynamoDBClient({ region: \\\"us-east-1\\\" })\\nconst input: CreateTableCommandInput = JSON.parse(await readFile(\\\"table.json\\\", \\\"utf8\\\"))\\nawait client.send(new CreateTableCommand(input))\\nawait waitUntilTableExists(\\n  { client, maxWaitTime: 600 },\\n  { TableName: \\\"VectorDocuments\\\" },\\n)\\nconsole.log(\\\"Table active; vector index readiness is checked before search.\\\")\\n\")), mdx(\"p\", null, mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"CreateTable\"), \" accepts \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"VectorIndexes\"), \"; to add an index later, use \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"UpdateTable.VectorIndexUpdates\"), \" with a \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"Create\"), \" action containing the same index configuration. Include attribute definitions for any new search-schema fields. Table existence alone does not establish vector-index readiness.\"), mdx(\"h3\", null, \"2. Generate embeddings and write documents\"), mdx(\"p\", null, \"Save \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"shared.mts\"), \". The \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://docs.aws.amazon.com/bedrock/latest/userguide/model-parameters-titan-embed-text.html\"\n  }, \"Titan V2 request format\"), \" uses \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"inputText\"), \", \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"dimensions\"), \" and \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"normalize\"), \". Request float embeddings, not binary embeddings.\"), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-ts\"\n  }, \"import { DynamoDBClient } from \\\"@aws-sdk/client-dynamodb\\\"\\nimport { DynamoDBDocumentClient } from \\\"@aws-sdk/lib-dynamodb\\\"\\nimport { BedrockRuntimeClient, InvokeModelCommand } from \\\"@aws-sdk/client-bedrock-runtime\\\"\\n\\nexport const tableName = \\\"VectorDocuments\\\"\\nexport const indexName = \\\"ByMeaning\\\"\\nexport const modelId = \\\"amazon.titan-embed-text-v2:0\\\"\\nexport const dimensions = 256\\nexport const dynamodb = new DynamoDBClient({ region: \\\"us-east-1\\\" })\\nexport const documents = DynamoDBDocumentClient.from(dynamodb)\\nconst bedrock = new BedrockRuntimeClient({ region: \\\"us-east-1\\\" })\\n\\nexport async function embed(inputText: string): Promise<number[]> {\\n  const response = await bedrock.send(new InvokeModelCommand({\\n    modelId,\\n    contentType: \\\"application/json\\\",\\n    accept: \\\"application/json\\\",\\n    body: JSON.stringify({ inputText, dimensions, normalize: true, embeddingTypes: [\\\"float\\\"] }),\\n  }))\\n  const payload = JSON.parse(new TextDecoder().decode(response.body))\\n  const vector: unknown = payload.embedding\\n  if (!Array.isArray(vector) || vector.length !== dimensions ||\\n      !vector.every((n) => typeof n === \\\"number\\\" && Number.isFinite(n))) {\\n    throw new Error(\\\"Embedding response has invalid coordinates or dimensions\\\")\\n  }\\n  return vector as number[]\\n}\\n\")), mdx(\"p\", null, \"Save \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"write.mts\"), \". The document client marshals the JavaScript number array into a DynamoDB List of Numbers:\"), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-ts\"\n  }, \"import { PutCommand } from \\\"@aws-sdk/lib-dynamodb\\\"\\nimport { documents, embed, modelId, tableName } from \\\"./shared.mts\\\"\\n\\nconst passages = [\\n  { id: \\\"acme#ttl\\\", title: \\\"Session expiration\\\", text: \\\"Use TTL to remove expired session records.\\\" },\\n  { id: \\\"acme#backup\\\", title: \\\"Recovering data\\\", text: \\\"Use point-in-time recovery to restore a table.\\\" },\\n  { id: \\\"acme#query\\\", title: \\\"Reading one customer\\\", text: \\\"Use a partition key to query customer records.\\\" },\\n]\\n\\nfor (const passage of passages) {\\n  const embedding = await embed(passage.text)\\n  await documents.send(new PutCommand({\\n    TableName: tableName,\\n    Item: { ...passage, tenantId: \\\"acme\\\", language: \\\"en\\\", embedding, embeddingModel: modelId },\\n    ReturnConsumedCapacity: \\\"INDEXES\\\",\\n  }))\\n}\\nconsole.log(`Wrote ${passages.length} documents`)\\n\")), mdx(\"p\", null, \"Run \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"npx tsx write.mts\"), \". Successful table writes do not guarantee that the new vectors are searchable immediately. These sample IDs are deterministic, so rerunning replaces the same three documents. In production, use source-version conditions to prevent an older embedding job from overwriting newer content.\"), mdx(\"p\", null, \"The local test, with synthetic embedding responses, printed \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"Wrote 3 documents\"), \". Reading the items back confirmed 256 coordinates and tenant \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"acme\"), \" for each of \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"acme#ttl\"), \", \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"acme#backup\"), \" and \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"acme#query\"), \". This verifies serialization and storage, not semantic ranking.\"), mdx(\"h3\", null, \"3. Search with SDK v3 and an inline filter\"), mdx(\"p\", null, \"Save \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"search.mts\"), \". It waits for \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"ACTIVE\"), \" with no backfill, then retries only the documented temporary missing-index error during search-endpoint propagation. The ten-minute deadline is an example application timeout, not an AWS readiness guarantee.\"), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-ts\"\n  }, \"import { setTimeout as sleep } from \\\"node:timers/promises\\\"\\nimport { DescribeTableCommand, SearchVectorsCommand } from \\\"@aws-sdk/client-dynamodb\\\"\\nimport { dynamodb, embed, indexName, tableName } from \\\"./shared.mts\\\"\\n\\nconst vector = await embed(\\\"How can I automatically remove expired sessions?\\\")\\nconst command = new SearchVectorsCommand({\\n  TableName: tableName,\\n  IndexName: indexName,\\n  SearchVector: vector.map((n) => ({ N: String(n) })),\\n  TopK: 3,\\n  SearchConditionExpression: \\\"#tenant = :tenant AND #lang = :lang\\\",\\n  ExpressionAttributeNames: { \\\"#tenant\\\": \\\"tenantId\\\", \\\"#lang\\\": \\\"language\\\", \\\"#text\\\": \\\"text\\\" },\\n  ExpressionAttributeValues: { \\\":tenant\\\": { S: \\\"acme\\\" }, \\\":lang\\\": { S: \\\"en\\\" } },\\n  ProjectionExpression: \\\"id, title, #text\\\",\\n  ReturnConsumedCapacity: \\\"TOTAL\\\",\\n})\\n\\nasync function searchWhenReady() {\\n  const deadline = Date.now() + 600_000\\n  while (Date.now() < deadline) {\\n    const description = await dynamodb.send(new DescribeTableCommand({ TableName: tableName }))\\n    const index = description.Table?.VectorIndexes?.find((i) => i.IndexName === indexName)\\n    if (index?.IndexStatus === \\\"ACTIVE\\\" && index.Backfilling !== true) {\\n      try {\\n        return await dynamodb.send(command)\\n      } catch (error) {\\n        const propagating = error instanceof Error && error.name === \\\"ValidationException\\\" &&\\n          /table does not have the specified index/i.test(error.message)\\n        if (!propagating) throw error\\n      }\\n    }\\n    await sleep(10_000)\\n  }\\n  throw new Error(\\\"Vector index not ready before deadline; inspect DescribeTable and retry later\\\")\\n}\\n\\nconst response = await searchWhenReady()\\nconsole.log(JSON.stringify(response.SearchResults ?? [], null, 2))\\nconsole.log(\\\"Search bytes:\\\", response.ConsumedCapacity?.VectorSearchRequestBytes)\\n\")), mdx(\"p\", null, \"Run \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"npx tsx search.mts\"), \". It searches only tenant \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"acme\"), \" and English documents. To search all languages for that tenant, remove the language clause and its unused name/value aliases; retain the tenant equality. A successful search can still return fewer than \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"TopK\"), \" matches, including none while recent writes propagate.\"), mdx(\"h3\", null, \"4. Run the same filtered search with boto3\"), mdx(\"p\", null, \"After the index is ready, install current \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"boto3\"), \" in a Python virtual environment and save this as \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"search.py\"), \". Use the low-level client so the typed number values are explicit; there is no need to pass Python floats through boto3's document serializer.\"), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-python\"\n  }, \"import json\\nimport boto3\\n\\nregion = \\\"us-east-1\\\"\\nbedrock = boto3.client(\\\"bedrock-runtime\\\", region_name=region)\\ndynamodb = boto3.client(\\\"dynamodb\\\", region_name=region)\\n\\nembedding_response = bedrock.invoke_model(\\n    modelId=\\\"amazon.titan-embed-text-v2:0\\\",\\n    contentType=\\\"application/json\\\",\\n    accept=\\\"application/json\\\",\\n    body=json.dumps({\\n        \\\"inputText\\\": \\\"How can I automatically remove expired sessions?\\\",\\n        \\\"dimensions\\\": 256,\\n        \\\"normalize\\\": True,\\n        \\\"embeddingTypes\\\": [\\\"float\\\"],\\n    }),\\n)\\nvector = json.loads(embedding_response[\\\"body\\\"].read())[\\\"embedding\\\"]\\nif len(vector) != 256:\\n    raise ValueError(\\\"Embedding dimensions do not match ByMeaning\\\")\\n\\nresponse = dynamodb.search_vectors(\\n    TableName=\\\"VectorDocuments\\\",\\n    IndexName=\\\"ByMeaning\\\",\\n    SearchVector=[{\\\"N\\\": str(value)} for value in vector],\\n    TopK=3,\\n    SearchConditionExpression=\\\"#tenant = :tenant AND #lang = :lang\\\",\\n    ExpressionAttributeNames={\\\"#tenant\\\": \\\"tenantId\\\", \\\"#lang\\\": \\\"language\\\", \\\"#text\\\": \\\"text\\\"},\\n    ExpressionAttributeValues={\\\":tenant\\\": {\\\"S\\\": \\\"acme\\\"}, \\\":lang\\\": {\\\"S\\\": \\\"en\\\"}},\\n    ProjectionExpression=\\\"id, title, #text\\\",\\n    ReturnConsumedCapacity=\\\"TOTAL\\\",\\n)\\nprint(json.dumps(response.get(\\\"SearchResults\\\", []), indent=2))\\nprint(\\\"Search bytes:\\\", response.get(\\\"ConsumedCapacity\\\", {}).get(\\\"VectorSearchRequestBytes\\\"))\\n\")), mdx(\"p\", null, \"The two search programs use the same model, dimensions, normalization and expression. Compare returned item IDs and scores on your own dataset; avoid hard-coding an assumed score for the TTL passage.\"), mdx(\"h2\", null, \"IAM permissions and tenant isolation\"), mdx(\"p\", null, \"A search-only application that generates its query embedding needs \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"dynamodb:SearchVectors\"), \" on the index ARN and \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_InvokeModel.html\"\n  }, \"bedrock:InvokeModel\"), \" on the embedding model. Replace the example account ID in this policy:\"), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-json\"\n  }, \"{\\n  \\\"Version\\\": \\\"2012-10-17\\\",\\n  \\\"Statement\\\": [\\n    {\\n      \\\"Effect\\\": \\\"Allow\\\",\\n      \\\"Action\\\": \\\"dynamodb:SearchVectors\\\",\\n      \\\"Resource\\\": \\\"arn:aws:dynamodb:us-east-1:123456789012:table/VectorDocuments/index/ByMeaning\\\"\\n    },\\n    {\\n      \\\"Effect\\\": \\\"Allow\\\",\\n      \\\"Action\\\": \\\"bedrock:InvokeModel\\\",\\n      \\\"Resource\\\": \\\"arn:aws:bedrock:us-east-1::foundation-model/amazon.titan-embed-text-v2:0\\\"\\n    }\\n  ]\\n}\\n\")), mdx(\"p\", null, \"The setup scripts additionally need \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"dynamodb:CreateTable\"), \" and \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"dynamodb:DescribeTable\"), \" on the table; writing needs \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"dynamodb:PutItem\"), \". The readiness loop also needs \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"DescribeTable\"), \". Adding or deleting an index on an existing table uses \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"dynamodb:UpdateTable\"), \".\"), mdx(\"p\", null, mdx(\"strong\", {\n    parentName: \"p\"\n  }, \"A tenant filter is not an authorization boundary.\"), \" DynamoDB's \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/VectorSearch.Security.html\"\n  }, \"vector security documentation\"), \" says fine-grained condition keys such as \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"dynamodb:LeadingKeys\"), \", \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"dynamodb:Attributes\"), \" and \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"dynamodb:Select\"), \" do not apply to \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"SearchVectors\"), \". A principal allowed to search this index can choose another tenant value. Derive the tenant from authenticated server-side context; for IAM-enforced isolation, use separately scoped data resources containing only the authorized tenant's data.\"), mdx(\"h2\", null, \"Synchronization, backfill and global tables\"), mdx(\"p\", null, \"Adding an index to existing data starts a backfill. \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"DescribeTable\"), \" reports \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"IndexStatus: CREATING\"), \", with \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"Backfilling: true\"), \" during population. There is no separate \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"BACKFILLING\"), \" status. AWS's \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/VectorSearchDataSync.html\"\n  }, \"synchronization guide\"), \" says new writes are captured during backfill, but searches fail until it completes. Even a small table can take time to build an index.\"), mdx(\"p\", null, \"After activation, inserts, updates and deletes propagate asynchronously. Missing vector attributes are not indexed. If an index defines a partition key and an item lacks it, the base-table write can succeed while the item remains absent from search. Deleting the vector attribute removes the index entry. A table read succeeding is therefore insufficient evidence that an item is searchable.\"), mdx(\"p\", null, \"With \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"/dynamodb-global-tables/\"\n  }, \"global tables\"), \", the index definition is replicated automatically to new replica Regions. Check the vector index's readiness in each Region, independently of the replica table's status. Searches run against the local Region's index. \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/VectorSearchGlobalTables.html\"\n  }, \"AWS documents support\"), \" for MREC, MRSC and multi-account global tables, subject to their usual configuration restrictions.\"), mdx(\"p\", null, \"MRSC strengthens table replication, not vector-index consistency. Local and cross-Region search can both lag acknowledged writes. ANN results can also differ slightly between Regions even after the underlying vectors agree. Replicated vector writes incur destination-Region vector write charges.\"), mdx(\"h2\", null, \"DynamoDB vector search pricing and a monthly example\"), mdx(\"p\", null, \"The following rates are for \", mdx(\"strong\", {\n    parentName: \"p\"\n  }, \"US East (N. Virginia), checked October 23, 2026\"), \". Vector charges are additional to base-table requests and storage.\"), mdx(\"table\", null, mdx(\"thead\", {\n    parentName: \"table\"\n  }, mdx(\"tr\", {\n    parentName: \"thead\"\n  }, mdx(\"th\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Charge\"), mdx(\"th\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Standard\"), mdx(\"th\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Standard-IA\"))), mdx(\"tbody\", {\n    parentName: \"table\"\n  }, mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Data written to vector indexes\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"$0.52 per GB\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"$0.65 per GB\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Search data processed and returned\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"$0.002 per GB\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"$0.0025 per GB\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Vector index storage\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"$0.25 per GB-month\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"$0.10 per GB-month\")))), mdx(\"p\", null, \"AWS's \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://aws.amazon.com/dynamodb/pricing/\"\n  }, \"DynamoDB pricing page\"), \" specifies per-byte billing with a 1 KB minimum per write or search. Writes include the vector and projected attributes. Initial backfill when adding an index to an existing table is free; subsequent writes and ongoing storage are billed.\"), mdx(\"p\", null, \"AWS's own example on that page uses 1 million items with 768-dimension embeddings, and 10 vector writes and 10 searches per second over a 30-day month: 25.92 million of each. Vector search adds \", mdx(\"strong\", {\n    parentName: \"p\"\n  }, \"$55.54 a month\"), \": $51.42 for writes, $3.17 for searches and $0.95 for index storage. The table itself adds $65.75, for \", mdx(\"strong\", {\n    parentName: \"p\"\n  }, \"$121.29\"), \" in total. Writes dominate because each is billed by size, and a 768-dimension vector alone is 3,072 bytes of coordinates.\"), mdx(\"p\", null, \"To compare table classes, take round metered totals instead: \", mdx(\"strong\", {\n    parentName: \"p\"\n  }, \"100 GB of vector writes, 2,000 GB of searches and 20 GB-month of index storage\"), \". These are example usage totals, not estimates derived from a document count.\"), mdx(\"table\", null, mdx(\"thead\", {\n    parentName: \"table\"\n  }, mdx(\"tr\", {\n    parentName: \"thead\"\n  }, mdx(\"th\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Component\"), mdx(\"th\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Standard calculation\"), mdx(\"th\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Monthly cost\"))), mdx(\"tbody\", {\n    parentName: \"table\"\n  }, mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Vector writes\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"100 \\xD7 $0.52\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"$52.00\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Vector searches\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"2,000 \\xD7 $0.002\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"$4.00\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Index storage\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"20 \\xD7 $0.25\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"$5.00\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, mdx(\"strong\", {\n    parentName: \"td\"\n  }, \"Incremental vector total\")), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"$52 + $4 + $5\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, mdx(\"strong\", {\n    parentName: \"td\"\n  }, \"$61.00\"))))), mdx(\"p\", null, \"The same metered usage on Standard-IA is $65 + $5 + $2 = \", mdx(\"strong\", {\n    parentName: \"p\"\n  }, \"$72.00\"), \". Cheaper storage does not necessarily make an active index cheaper overall. Add base-table requests/storage, embedding generation, backups and any replication or transfer charges separately. The \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"/dynamodb-pricing-calculator/\"\n  }, \"DynamoDB pricing calculator\"), \" helps estimate the underlying table portion.\"), mdx(\"p\", null, \"Do not estimate search cost as \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"query vector bytes \\xD7 request count\"), \". Search bills for data examined and returned. AWS describes logarithmic growth with index size, but that is not a complete billing formula. Use \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"ConsumedCapacity.VectorSearchRequestBytes\"), \" and \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"VectorWriteRequestBytes\"), \", or their CloudWatch metrics, as described in \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/VectorSearchMonitoring.html\"\n  }, \"vector capacity monitoring\"), \". Sum metered bytes and divide by 1,073,741,824 to obtain DynamoDB GB; include the per-request minimum before aggregating.\"), mdx(\"p\", null, \"For example, a 256-dimensional f32 vector contains 1,024 bytes of coordinates, but projected text, keys and search traversal add work. Returning fewer attributes reduces returned bytes; choosing a smaller embedding model can reduce storage and processing, subject to relevance testing.\"), mdx(\"h2\", null, \"Vector search quotas and limitations\"), mdx(\"p\", null, \"These vector-specific limits are distinct from ordinary GSI limits. The \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ServiceQuotas.html\"\n  }, \"AWS service quotas\"), \" list:\"), mdx(\"table\", null, mdx(\"thead\", {\n    parentName: \"table\"\n  }, mdx(\"tr\", {\n    parentName: \"thead\"\n  }, mdx(\"th\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Constraint\"), mdx(\"th\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Default or maximum\"), mdx(\"th\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Increase path\"))), mdx(\"tbody\", {\n    parentName: \"table\"\n  }, mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Vector indexes per table\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"5\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"AWS Support\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Dimensions\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"4,096\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Fixed\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, mdx(\"inlineCode\", {\n    parentName: \"td\"\n  }, \"TopK\")), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"100\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Fixed\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, mdx(\"inlineCode\", {\n    parentName: \"td\"\n  }, \"HASH\"), \" attributes per vector index\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"1\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Fixed\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Inline filter attributes per index\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"18\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Fixed\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Search throughput per partition-key value\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"1 GB/s\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"AWS Support\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Index write throughput per partition-key value\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"10 MB/s\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"AWS Support\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Base-table size for index creation without allowlisting\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"600 GB\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"AWS Support\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Concurrent vector index creates/deletes per table\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"1\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Fixed\")))), mdx(\"p\", null, \"The search throughput quota counts bytes processed, not API calls or returned matches. The 600 GB figure is an index-creation threshold, not an ongoing table-size limit. See the wider \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"/dynamodb-limits/\"\n  }, \"DynamoDB limits reference\"), \" for item and table constraints.\"), mdx(\"p\", null, \"Additional \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/VectorSearch.Requirements.html\"\n  }, \"documented restrictions\"), \" include a 16 MB search-response limit with no pagination, on-demand capacity only, and no vector-index \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"Query\"), \", \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"Scan\"), \" or PartiQL access. A high \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"TopK\"), \" and large projected items can hit the response limit. DAX does not support \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"SearchVectors\"), \".\"), mdx(\"h2\", null, \"DynamoDB vs OpenSearch, S3 Vectors and pgvector\"), mdx(\"p\", null, \"Choose based on retrieval requirements and where the source of truth lives. These are workload recommendations based on the documented capabilities, not a cross-service benchmark.\"), mdx(\"table\", null, mdx(\"thead\", {\n    parentName: \"table\"\n  }, mdx(\"tr\", {\n    parentName: \"thead\"\n  }, mdx(\"th\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Option\"), mdx(\"th\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Choose it when\"), mdx(\"th\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"What you take on\"))), mdx(\"tbody\", {\n    parentName: \"table\"\n  }, mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Native DynamoDB vector index\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Operational data already lives in DynamoDB; you need ANN retrieval with tenant/category scoping and equality filters\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"On-demand tables, eventual search visibility, limited filter operators and no search pagination\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"OpenSearch through DynamoDB zero-ETL\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"You need lexical plus vector search, richer search queries, relevance tuning or aggregations\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"An ingestion pipeline and a separately billed search service; monitor synchronization and search capacity\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Amazon S3 Vectors\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"A large embedding corpus needs cost-oriented storage and retrieval, without serving general transactional records from the same system\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Separate vector storage and source-data lifecycle; evaluate its documented latency for your workload\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Aurora PostgreSQL with pgvector\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Vectors belong beside relational data and retrieval needs SQL joins, transactions or complex predicates\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Database capacity, query plans and index tuning; ANN filters can require extra candidates or iterative scans\")))), mdx(\"p\", null, mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/OpenSearchIngestionForDynamoDB.html\"\n  }, \"OpenSearch zero-ETL\"), \" loads an initial export, then follows DynamoDB Streams. The snapshot route needs PITR; ongoing replication needs new and old stream images. It avoids a custom synchronization implementation, but does not eliminate ingestion and search-service charges. \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://docs.aws.amazon.com/opensearch-service/latest/developerguide/vector-search.html\"\n  }, \"OpenSearch vector search\"), \" includes semantic and hybrid retrieval capabilities.\"), mdx(\"p\", null, mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-vectors.html\"\n  }, \"S3 Vectors\"), \" provides dedicated vector buckets, indexes and metadata filtering. AWS describes subsecond latency for infrequent queries and latency as low as 100 milliseconds for more frequent queries, and documents strongly consistent writes. It is a different storage API, not an index over a DynamoDB table.\"), mdx(\"p\", null, mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/AuroraPostgreSQL.VectorDB.html\"\n  }, \"Aurora PostgreSQL supports pgvector\"), \", including use as a Bedrock Knowledge Base. The \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://github.com/pgvector/pgvector\"\n  }, \"pgvector project\"), \" supports exact search and HNSW/IVFFlat approximate indexes. With approximate indexes, filtering can happen after candidate retrieval, so review iterative scanning and indexing choices instead of assuming a SQL \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"WHERE\"), \" automatically preserves recall. For broader operational tradeoffs, see \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"/dynamodb-alternatives/\"\n  }, \"DynamoDB alternatives\"), \".\"), mdx(\"h2\", null, \"Use cases and pitfalls that affect retrieval quality\"), mdx(\"ul\", null, mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"strong\", {\n    parentName: \"li\"\n  }, \"Semantic search:\"), \" match a question to documentation or a description to products. Evaluate synonyms, ambiguous queries and domain terminology.\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"strong\", {\n    parentName: \"li\"\n  }, \"RAG:\"), \" retrieve document chunks and their source identifiers, then give the selected text to a generation model. The example implements retrieval, not automatic answer generation or a managed Bedrock Knowledge Base integration.\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"strong\", {\n    parentName: \"li\"\n  }, \"Agent memory:\"), \" retrieve relevant prior observations within an authorized user's scope. Preserve timestamps and source versions, and enforce retention in the application when physical deletion can lag.\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"strong\", {\n    parentName: \"li\"\n  }, \"Recommendations:\"), \" compare product or content embeddings; select the metric according to whether vector magnitude should affect ranking.\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"strong\", {\n    parentName: \"li\"\n  }, \"Near-duplicate detection:\"), \" retrieve candidate pairs, then verify them with an application-specific threshold or exact comparison. ANN is not a uniqueness constraint.\")), mdx(\"p\", null, \"Common failures include a vector with the wrong dimension count, missing routing attributes, mixing embedding models, interpreting cosine distance backwards, and updating text without its embedding. Narrow equality filters can leave few eligible neighbors. Check index membership and filter values before treating an empty result as poor embedding quality.\"), mdx(\"p\", null, \"For frequent updates, store a source version with the embedding and reject stale background writes. For sensitive or recently deleted content, validate current authorization and availability before returning retrieved text. Eventual search visibility makes this relevant even when the base table has strong reads. AWS's \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/VectorSearchBestPractices.html\"\n  }, \"vector best practices\"), \" also cover partition design, selective projection and model migrations.\"), mdx(\"p\", null, \"Once a real index is ready, \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"/dynamodb-semantic-search/\"\n  }, \"Dynobase's semantic search\"), \" lets you inspect matches in its desktop interface. Use the same model and dimensions as the stored embeddings when comparing queries.\"), mdx(\"p\", null, mdx(\"img\", {\n    parentName: \"p\",\n    \"src\": \"/images/features-3/semantic.jpg\",\n    \"alt\": \"Dynobase semantic search interface showing results from a DynamoDB vector index.\"\n  })), mdx(FAQ, {\n    questions: [{\n      question: \"Does DynamoDB support vector search?\",\n      answer: \"Yes. Native vector indexes and the SearchVectors API became generally available on August 5, 2026. They require an on-demand table and support approximate nearest neighbor searches over embeddings stored with your items.\"\n    }, {\n      question: \"Can DynamoDB be a vector database for RAG?\",\n      answer: \"Yes. Store document chunks and embeddings, retrieve similar chunks through a vector index, and pass their text to a generation model. DynamoDB stores and searches the vectors; your application generates embeddings and assembles the RAG workflow.\"\n    }, {\n      question: \"How do I store embeddings in DynamoDB?\",\n      answer: \"Use a List of Numbers with the exact dimension count configured on the vector index. Generate query and document embeddings with the same model. The index stores coordinates at 32-bit floating point precision.\"\n    }, {\n      question: \"Is DynamoDB vector search strongly consistent?\",\n      answer: \"No. Vector indexing is asynchronous, including on MRSC global tables. A successful write or a strongly consistent base-table read does not guarantee that SearchVectors already sees that version.\"\n    }, {\n      question: \"How much does DynamoDB vector search cost?\",\n      answer: \"In us-east-1 Standard tables, vector writes cost $0.52 per GB, searches $0.002 per GB processed and returned, and index storage $0.25 per GB-month. Writes and searches have a 1 KB minimum; base-table and embedding-model charges are additional.\"\n    }, {\n      question: \"Can I test vector search with DynamoDB Local?\",\n      answer: \"DynamoDB Local does not implement SearchVectors. Use it for ordinary item writes and reads, validate vector request shapes with current SDKs, and test real index behavior in AWS.\"\n    }],\n    mdxType: \"FAQ\"\n  }));\n}\n;\nMDXContent.isMDXComponent = true;","frontmatter":{"publishedDate":"2026-10-23","updatedDate":"2026-10-23","path":"/dynamodb-vector-search/","metaTitle":"DynamoDB Vector Search: API, Examples and Pricing","metaDescription":"Build DynamoDB vector search with native indexes, Bedrock embeddings and SearchVectors. Includes SDK examples, quotas, pricing and database comparisons.","title":"DynamoDB vector search: indexes, examples, pricing and limits","authorName":"Rafal Wilinski","authorLink":"https://x.com/rafalwilinski","authorImage":"/images/authors/rafal-wilinski.jpg","image":"/images/posts/dynamodb-vector-search/social.png"}}},"pageContext":{}},
    "staticQueryHashes": ["3649515864"]}