{"slug": "dynamodb-now-does-vector-search", "title": "DynamoDB Now Does Vector Search", "summary": "AWS has made vector search generally available in Amazon DynamoDB, promising single-digit millisecond searches and 99%+ recall at any scale. The feature supports up to 4,096 dimensions and multiple distance functions, but documentation reveals a hard requirement that may exclude many existing tables and a security warning for multi-tenant applications.", "body_md": "*Originally published on Build With AWS. Subscribe for weekly AWS builds.*\n\nOn August 5, 2026, AWS made vector search [generally available](https://aws.amazon.com/blogs/aws/amazon-dynamodb-now-supports-real-time-vector-search-at-any-scale/) in Amazon DynamoDB.\n\nThe headline promises single-digit millisecond searches, 99%+ recall, and a design that reaches trillions of vectors.\n\nThe reaction across engineering forums split in two within hours.\n\nOne group read it as the end of a product category, with variations on “so I don’t need S3 Vector buckets anymore?” and “MongoDB is finished.”\n\nAnother group opened the service quotas page and came back with a much narrower reading, pointing out that the documented way to hold latency down and scale search throughput as your index grows is to keep each query scoped to a manageable partition.\n\nBoth readings are defensible from the announcement alone.\n\nThe documentation settles it, and it also contains three things the announcement never mentions: a hard requirement that rules out many existing tables, a security warning that matters enormously for multi-tenant applications, and a pricing example where vector writes cost far more than searches.\n\nBefore any of that makes sense, we need to talk about what a vector actually is, because the rest follows from it.\n\nImagine you run a bookstore and you want to arrange books so that similar ones sit near each other.\n\nYou could sort alphabetically, but then a cookbook lands beside a book on cosmology. Instead, suppose you give every book a set of coordinates, the way a city gives every building a street address.\n\nOne coordinate might loosely capture “how technical is this,” another “how much does this concern food,” another “how narrative is this.”\n\nBooks about pasta end up clustered in one corner of the room. Books about black holes end up in a different corner.\n\nAn **embedding** is exactly that: a list of numbers that acts as an address describing the meaning of a piece of text.\n\nA machine learning model reads your text and produces the address.\n\nTwo pieces of text that mean similar things get addresses that sit close together.\n\nThat closeness is the whole trick, and it is why the technique works for search: you convert the shopper’s phrase “lightweight running shoes for summer” into an address, then look for products whose addresses are nearby.\n\nYou never match keywords. You match meaning.\n\nThat is why people call it **semantic search**, and it is why a search for “footwear for hot weather” can surface a product whose description never uses either word.\n\nThe number of coordinates is called the number of **dimensions**. Our bookstore used three. Real models use hundreds or thousands, because meaning is complicated and three numbers cannot capture it. DynamoDB accepts up to 4,096 dimensions.\n\nBecause there are many ways to measure “near,” you have to pick one, called the **distance function**.\n\nPicture each address as an arrow drawn from the middle of the room out to that point. You now have two arrows, one for the shopper’s query and one for a product, and three sensible ways to compare them.\n\n**Cosine** distance only cares about the angle between the arrows, ignoring their length. It asks “are these pointing the same way,” which for text means “are these about the same thing,” while ignoring how emphatically each one says it.\n\n**Euclidean** distance is the tape-measure answer: how far apart are the two arrowheads in a straight line. Length matters here, so a long arrow and a short arrow pointing identically still count as far apart.\n\n**Dot product** is the one worth slowing down for, because everyone repeats the phrase “it considers direction and magnitude” without saying what it does.\n\nThink of two people pushing a shopping cart. If both push in the same direction, the work they get done depends on the direction *and* on how hard each pushes: two people shoving hard in agreement moves the cart much further than two people nudging it gently.\n\nIf one pushes sideways, their effort barely contributes. If one pushes backwards, they actively subtract. The dot product is that number, agreement scaled by effort, which is precisely why dot product scores can come out **negative** when the two arrows point opposite ways.\n\nAWS calls Cosine the safe default when you are unsure, and otherwise recommends matching whatever measure your embedding model’s own documentation specifies.\n\nDot product then comes with a choice worth understanding rather than following blindly.\n\nAWS recommends **normalizing** your embeddings to unit length, which means rescaling every arrow to exactly the same length so only direction can differ. Do that and dot product ranks results identically to Cosine, because you have removed the “how hard each person pushes” part and left only “do they agree.”\n\nSkip normalization only when you *want* length to carry meaning. The documentation’s example is a recommendation system that stretches each product’s arrow in proportion to its popularity score, so popular products push harder and rank higher.\n\nOne trap here has caught people in every vector database that offers a choice.\n\nFor Cosine and Euclidean, a **lower** score means a **closer** match, with zero meaning identical. For Dot product, higher means closer. The comparison flips depending on a setting you chose weeks earlier, and nothing stops you from sorting the wrong way.\n\nTwo related details are easy to get wrong: Cosine distance here runs from 0 for identical direction up to 2 for opposite directions, not 0 to 1, and Dot product scores can be **negative** for vectors pointing the opposite way.\n\nIf you write a relevance threshold assuming scores never go below zero, it will behave strangely on exactly the results you meant to exclude.\n\nWhat DynamoDB shipped is not a new data type for any of this.\n\nYou store the embedding in the ordinary List type, where each element is a Number holding one coordinate, and you write it with a normal PutItem or UpdateItem call. No new data type and no change to your item schema is required, though as the next section covers, you may still need to change one setting on the table itself.\n\nWhat is new is a new kind of **index**. An index is a second, reorganized copy of your data that DynamoDB maintains for you, kept in a shape that makes one particular question fast, the way a library keeps a card catalog sorted by author alongside shelves sorted by subject.\n\nYou declare a vector index on the attribute holding your embeddings, then query it through a new SearchVectors call that takes a query address, a count of how many neighbors you want (up to 100, called **top-K**), and optional filters.\n\nTwo words from that setup will recur, so here they are up front.\n\nThe **SearchSchema** is simply the bundle of settings you declare when creating the index, holding the grouping attribute and the attributes you want to filter on. It is the form you fill in when you order the card catalog.\n\nThe **projection** is your choice of which of the item’s other attributes get copied onto the index entry alongside the vector, the way a catalog card carries the title and author but not the book’s full text.\n\nCopy little and the card is cheap but you have to go fetch the book to read anything else.\n\nCopy everything and the card is self-sufficient but expensive, in ways the pricing section gets specific about.\n\nAlmost every design choice about that index is fixed the moment you create it.\n\nYou cannot change the number of dimensions or the distance function.\n\nThe SearchSchema is fixed at creation, and the documentation is explicit that you cannot add, remove, or change the partition key afterward.\n\nProjection choices are fixed too: with an INCLUDE projection you cannot later change which attributes are included.\n\nChanging any of these means creating a second index and migrating to it, which AWS documents as a four-step dance: create the new index under a different name, wait for it to finish **backfilling**, cut your application over, then delete the old one to stop paying for its storage.\n\nBackfilling is what happens when you point an index at a table that already holds data: DynamoDB walks every existing item and builds the index entry for it, because an index created today knows nothing about items written last year.\n\nIt is the clerk who has to sit down and type up a catalog card for every book already on the shelves before the catalog is any use to anyone.\n\nYour base table is never affected, because DynamoDB re-derives the index from your items. But it does mean the design work happens up front, and this is the reason the rest of this post exists.\n\nFinally, the 99%+ recall figure in the announcement is the most informative number in it.\n\n**Recall** means: of the genuinely closest neighbors, what fraction did the search actually find? A figure below 100% tells you this is **approximate nearest neighbor** search, and AWS documents it as such.\n\nRather than comparing your query against every stored vector, which would be like reading every book in the building, the system uses a structure that walks it quickly to the right neighborhood and looks around there.\n\nIt usually finds the true nearest neighbors and occasionally misses one.\n\nAt large scale, production vector systems generally work this way, because the exact version does not survive contact with a billion items.\n\nWhat matters practically is that AWS states a recall figure and gives you no knob to tune it. You get 99%+ or you use something else.\n\nBefore evaluating anything else, check two facts about your table, because either one can end the conversation.\n\nThe first is not mentioned in the announcement at all.\n\nDynamoDB bills capacity in two modes.\n\n**Provisioned** mode means you tell AWS in advance how much traffic to reserve, like booking a fixed number of restaurant tables for the evening.\n\n**On-demand** mode means you pay per request and AWS handles the scaling, like walking in and being seated.\n\nVector indexes are supported only on tables using on-demand capacity mode, and are not supported on provisioned capacity tables.\n\nIf your production table runs provisioned capacity, which many cost-optimized tables do precisely because it is cheaper for steady predictable traffic, you must switch it to on-demand before you can add a vector index.\n\nThat is a real change to your cost profile, and it needs to be part of the evaluation rather than a surprise during implementation.\n\nThe second is a self-service threshold rather than a true ceiling.\n\nYou can create a vector index on a base table up to 600 GB without asking anyone. Above that, the quota is adjustable, but you have to go through AWS Support to raise it.\n\nAWS does not publish a reason for the threshold, so I will not invent one.\n\nThe practical consequence is simply that the largest existing DynamoDB tables cannot self-serve their way into this feature and need a conversation first.\n\nDynamoDB’s default quotas are **1 GBps of vector search and 10 MBps of vector writes, per partition key value**. Both are adjustable through AWS Support, so treat them as the shape of the system rather than a wall.\n\nA **partition key** is the label DynamoDB uses to decide which group your data belongs to. In our bookstore, it is which branch of the shop a book lives in.\n\nEvery SearchVectors call must name exactly one partition key value, so every search happens inside one branch. You cannot search two branches in one call.\n\nThat constraint is what makes the whole thing fast.\n\nA partition key restricts each search to the portion of the index belonging to a single value, and the call does not search the entire index.\n\nSearching less data lowers cost, can improve latency and recall, and scales throughput sideways as you add more values.\n\nFifty branches give you roughly fifty times the total search and write capacity of one, because each branch gets its own 1 GBps allowance.\n\nThis is why the trillion-vector claim and the per-partition quota are both true at once, and it is worth being precise rather than dramatic about it.\n\nAWS documents no storage limit for vector indexes, so the system as a whole genuinely has no size ceiling. Throughput, meanwhile, stays governed by those per-partition-key quotas.\n\nHorizontal partitioning is the primary way to scale out, adding branches rather than enlarging one, and the per-partition quotas can also be raised through Support if a single branch genuinely needs more.\n\nAWS’s own worked example makes the tradeoff concrete: a 768-dimension embedding plus 1 KB of other item data comes to roughly 4 KB per item, which works out to about 250,000 vectors examined per second and about 2,500 vector writes per second, per partition key value. As the number of vectors in a partition grows, each search examines more data and you approach the limit sooner.\n\nSo the partition key is your central design decision, and the guidance is more subtle than “pick something with lots of distinct values.” AWS says to avoid extremes in **both** directions.\n\nThe word for this is **cardinality**, which just means how many different values an attribute actually takes across your data. A yes-or-no flag has a cardinality of two.\n\nA country field has around two hundred. An order ID has as many values as you have orders, one apiece. Both ends of that scale hurt you here, for opposite reasons.\n\nToo few distinct values fails the obvious way. A boolean gives you two branches, most items land in one of them, and you get almost no throughput scaling and little of the latency or cost benefit.\n\nToo many distinct values fails in a way that is easy to miss, and it is the more interesting failure. If you partition by something nearly unique, like an item ID, each branch ends up holding a single item. A nearest-neighbor search inside a branch with one occupant has no neighbors to compare against, so **recall gets worse, not better**. You have not made search faster, you have made it meaningless.\n\nSplitting a bookstore into one building per book does not help anyone find a similar book.\n\nThe documentation’s example sits in the middle: location data partitioned by US state gives you about fifty values, each holding a meaningful population of vectors for good recall, and about fifty times the horizontal throughput. Good candidates have low-to-medium cardinality relative to the size and distribution of your dataset, hold enough vectors per value that nearest-neighbor search still has a meaningful population to search, and line up with a scope your application naturally searches on its own.\n\nTenant, workspace, geography, product category, or document collection can all work, but only when each value contains a real population. User ID is excellent if each user accumulates thousands of memory items and poor if each user has five. Nothing is automatically a good partition key.\n\nThe constraint also runs the other direction, which forces genuine design work. If your application truly needs to search across all tenants or all collections at once, you have two choices.\n\nYou can omit the partition key and accept one shared search space, where every query competes for a single allowance and examines more data as your indexed collection grows.\n\nOr you can issue N separate SearchVectors calls and merge the ranked results yourself.\n\nMerging is easy when the distance function is consistent across calls, but you pay for the aggregate bytes examined and returned across all N calls, and you inherit both the extra code and a worse **tail latency**.\n\nTail latency is the slow end of your response-time spread: not how long a typical request takes, but how long the unlucky few take. Fan-out makes it worse for a specific reason.\n\nA fan-out query cannot finish until its slowest branch answers, and the more branches you query in parallel, the higher the chance that at least one of them lands in its own slow tail.\n\nChoose carefully, because this is the decision the title of this post is about.\n\nTo filter more narrowly inside a partition, use inline filters instead, which the next sections cover.\n\nThis deserves its own section because it is the single most consequential thing in the documentation that the announcement does not mention, and because the natural way to use partition keys walks straight into it.\n\nIf you partition by tenant ID, it is tempting to conclude you have isolated your tenants. You have not.\n\nThe documentation is worth reading slowly: partition key scoping is a data-locality and performance optimization, not an access-control mechanism.\n\nAny **principal** holding dynamodb:SearchVectors permission on the index can search **any** partition key value.\n\nPrincipal is AWS’s word for whoever is making the call, whether that is a human user, an application, or another AWS service acting on your behalf.\n\nThe reason is a gap in the permission system.\n\nPermissions in AWS are written as **IAM** policies, IAM being Identity and Access Management, the service that decides who is allowed to do what.\n\nDynamoDB normally offers **fine-grained access control**, which lets an IAM policy say “this credential may only touch rows whose key starts with this tenant’s ID,” via a condition called dynamodb:LeadingKeys.\n\nThink of it as a keycard that opens only your own floor of the building. That condition does not apply to SearchVectors.\n\nFine-grained access control is not supported for the SearchVectors API. The keycard reader is not installed on this door.\n\nThe practical consequence: a partition key is a signpost telling the search where to look, not a wall preventing it from looking elsewhere.\n\nAny bug, and any code path where the caller gets to influence which partition key value your service searches on their behalf, becomes a cross-tenant data leak, and no IAM policy will stop it.\n\nThe shape to watch for is a tenant identifier that arrives in the request instead of being derived from the authenticated session, because at that point the caller is choosing which tenant’s data your trusted credentials go read.\n\nIf your workload requires strict tenant isolation at the data layer, AWS’s own recommendation is to use separate tables or separate indexes with distinct IAM grants per tenant, and to accept the operational cost that comes with that.\n\nVector search bills on three dimensions, all charged on top of the normal costs of the underlying table:\n\nLook at the first two rates together.\n\nPer gigabyte, writing costs **260 times more than searching**. That ratio is the most surprising thing on the pricing page, and it points the opposite way from where most people expect the money to go.\n\nAWS’s own worked example shows it landing. Take a knowledge base of one million items with 768-dimension vectors and 1 KB of projected attributes, running ten writes and ten searches per second for thirty days.\n\nThe searches, all 25.92 million of them, process 1,586 GB and cost **$3.17**.\n\nThe writes, also 25.92 million of them, cost **$51.42**. Storage adds $0.95. With equal numbers of reads and writes, the writes dominate by roughly sixteen times.\n\nBe careful about what that does and does not prove. It is not a law that writes always dominate.\n\nYour own balance depends on how often your content changes, how many searches you serve, how big each partition is, how many dimensions you chose, how much you project, and therefore how much data each search examines.\n\nA workload serving millions of searches against a rarely-updated set of documents can easily spend more on searching than on writing.\n\nWhat the example does establish is that the write side deserves attention it usually does not get, and that backfilling embeddings for an existing table is a real one-time cost worth estimating before you start.\n\nOne detail from the monitoring documentation turns into a genuine optimization. You are charged vector write capacity each time you write, update, or delete an item in a way that **changes an attribute the vector index holds**, and writes that touch nothing in the index cost nothing on it.\n\n**The condition matters more than it first appears.**\n\nIf a frequently-updated field such as a view counter is not projected into the index and is not part of its SearchSchema, updating it incurs no vector write charge.\n\nBut with ProjectionType: ALL, that counter *is* in the index, so every increment is a vector write you pay for.\n\nThis is one of the places where a lazy projection choice quietly becomes a recurring bill, which leads directly into the next point.\n\nOn the search side, resist the temptation to reverse-engineer per-query cost from index size.\n\nAWS does not publish what fraction of an index a query examines, and the honest answer is that you cannot derive it from the documentation.\n\nWhat you can do is measure it, because DynamoDB reports it directly.\n\nSet ReturnConsumedCapacity on your requests and you get back VectorSearchRequestBytes for searches and VectorWriteRequestBytes for writes, both also published to CloudWatch, AWS’s monitoring service for metrics from AWS services and applications.\n\nThose two metrics, measured against your own data and your own query mix, will tell you more than any published estimate.\n\nTwo more levers matter for cost, both about restraint.\n\nProjection controls which table attributes get copied into the index, and a broader projection increases both storage and write cost. Project only what you read directly from search results and fetch the rest with a follow-up GetItem.\n\nSeparately, returning the vector attribute itself in your results is expensive, because the response then carries the full list of coordinates. You almost never need it.\n\nFinally, dimensions cost money twice. A 1,536-dimension vector uses roughly four times the vector storage of a 384-dimension one, and higher dimensions raise both search and write charges because every vector carries more data.\n\nEmbeddings are stored in the index at 32-bit floating point precision, about four bytes per dimension, so the vector portion of a 1,536-dimension entry runs roughly 6 KB before you add projected attributes.\n\nHigher-precision values are accepted but lose precision on the way into the index. Choose the smallest number of dimensions that meets your relevance needs, and remember you cannot change it later.\n\nSeveral limitations are documented clearly and are easy to miss when you are reading a launch post.\n\n**Search results are eventually consistent.** The documentation states that there may be a brief delay between writing or updating a vector and its appearing in search results.\n\n“Real-time” in the launch title describes how fast a search returns, not how fast a new vector becomes findable.\n\nFor many product-catalog workloads a brief propagation delay is acceptable, though not all of them: newly added items, price changes, and stock status can all be cases where it is not.\n\nFor **agent memory**, where an AI assistant stores what it learned during one turn of a conversation so it can look the fact up on the very next turn, it becomes a correctness question.\n\nEither way, measure the actual lag against your own write pattern before you design around it.\n\n**Filters are exact-match only.** Inline filters let you narrow results on non-vector attributes, up to 18 per index, but only on exact values.\n\nNo BETWEEN, no BEGINS_WITH, no ranges of any kind.\n\nThat excludes a lot of what people actually want: price ranges, date windows, numeric thresholds, prefix matching.\n\nThe workaround is bucketing, encoding a price as a tier or a timestamp as a day key and matching exactly against the bucket.\n\nIt works, at the cost of granularity and a schema decision you must get right before building the index.\n\n**There is no keyword search.** DynamoDB offers no lexical or BM25 component, meaning no scoring based on literal word matches.\n\n**Hybrid search**, which blends literal matching with semantic matching and often beats either alone for document retrieval, is therefore not a single call here. You either run a second system for the lexical half and combine results in your application, or you accept semantic-only retrieval.\n\n**Responses cap at 16 MB with no pagination.** You cannot ask for the next page. The documentation warns about the specific combination that hits this: projecting all attributes, with large items, at a high top-K.\n\nIf your items are big, narrow the projection or lower top-K.\n\n**You cannot use Query, Scan, or PartiQL against a vector index.** Those are DynamoDB’s three normal ways of reading data, PartiQL being an SQL-like query language AWS offers as an alternative to the native API for people who would rather write something resembling SELECT.\n\nNone of them work here. SearchVectors is the only way to read from a vector index.\n\n**DynamoDB will not regenerate your embeddings.** This one causes silent, hard-to-debug quality decay. If you edit a product description and do not recompute its embedding, the index keeps answering from the old address.\n\nThe text and its meaning-coordinates have drifted apart, and nothing errors out. Search quality just quietly gets worse.\n\nAWS suggests catching content changes with **DynamoDB Streams**, a feed that reports every change made to your table as it happens, like a conveyor belt carrying a receipt for each edit past you, and running a downstream process that reads those receipts, regenerates the affected embeddings, and writes them back.\n\n**Build that on day one, not after someone complains about relevance.**\n\n**An item can vanish from search results without any error.**\n\nIf you remove the partition key attribute from an item, or forget to include it when writing, DynamoDB does not complain.\n\nThe item is silently de-indexed and stops appearing in searches, even though the base table row and its embedding are both still sitting there perfectly intact.\n\nThe book is still in the building; you just tore the branch label off its spine, and now nobody can find it.\n\nIf an item mysteriously disappears from results, check whether its partition key attribute is still present.\n\n**You cannot search an index while it is still filling up.** After you create a vector index, DynamoDB backfills it from your existing items.\n\nSearching before that finishes returns an error. Poll DescribeTable until IndexStatus is ACTIVE and Backfilling is false.\n\nThe same applies after restoring a table from a backup or from point-in-time recovery, DynamoDB’s continuous backup feature that lets you rewind a table to any second within a retention window, because in both cases DynamoDB rebuilds the index from the restored data rather than copying the old index wholesale.\n\nThe clerk has to retype every card.\n\n**DAX does not support SearchVectors.** DAX is DynamoDB Accelerator, a cache that sits in front of your table and keeps recently-read items in memory so repeat reads skip the database entirely, the way a shop clerk keeps the ten most-requested titles on the counter instead of walking to the shelves each time.\n\nVector searches cannot use it. If your application reads through DAX today, vector searches have to bypass the counter and go to DynamoDB directly, which means they do not get the cache’s latency benefit.\n\nYour ordinary cached reads carry on unaffected.\n\nOne small piece of good news among all this: only items that actually contain a valid vector attribute get replicated into the index.\n\nItems without an embedding consume no vector index storage, so you can mix indexed and non-indexed items in the same table without paying for the latter.\n\n**Global tables** are DynamoDB’s way of keeping copies of the same table in several AWS Regions at once, so users in Frankfurt and Sydney each read from a nearby copy instead of reaching across an ocean.\n\nEach copy is a **replica**. If you run global tables, DynamoDB creates the vector index on every replica automatically from the definition you gave it once, so you do not set it up Region by Region.\n\nTwo behaviors are worth knowing.\n\nCopying a new vector to the other Regions and indexing it there happen **asynchronously**, meaning the write finishes and confirms before the other copies have caught up, so a vector written in Frankfurt may not be findable in Sydney for a moment.\n\nThis holds even on tables using multi-Region strong consistency, the stricter mode where a strongly consistent read against any replica is guaranteed to see the latest successful write. That guarantee covers strongly consistent reads, and vector search sits outside it.\n\nAnd because the search is approximate, the same query against identical data in two Regions can legitimately return slightly different results or ordering. That is not a bug to chase.\n\nThe state of local development support is worth confirming separately before you commit a team to this path. I found no current official documentation stating whether DynamoDB Local supports vector indexes, so treat it as an open question to verify rather than an assumption either way.\n\nThe “goodbye S3 Vectors” reaction is the wrong conclusion, and the pricing structures show why they are built for different jobs.\n\nS3 Vectors charges $0.06 per GB-month for storage against DynamoDB’s $0.25 on the Standard table class, roughly 4.2 times cheaper, and $0.20 per GB uploaded against $0.52. A table class is which pricing plan a DynamoDB table sits on, and that storage gap narrows if you move to the Standard-Infrequent Access class, which cuts storage to 40% of Standard while raising request charges to 125%.\n\nS3 Vectors also charges a fixed $2.50 per million queries plus tiered data processing that gets cheaper as the index grows, plus a charge for data returned above a small free allowance.\n\nDynamoDB has no fixed per-request fee at all; you pay purely for bytes processed and returned.\n\nRead those structures side by side and the split is clear. S3 Vectors is priced to reward large indexes queried at moderate rates. DynamoDB is priced to reward small partitions queried at high rates with low latency.\n\nRather than assigning use cases absolutely, it is more accurate to say which way each option leans:\n\nTwo capabilities in that list carry the weight, because the loose phrase “you no longer need Postgres or OpenSearch” leans on both.\n\nAn aggregation answers a question about a group rather than about individual rows, such as how many matches fall in each category, and vector search returns neither. A join answers one question from two separately stored collections at once, such as returning matching products along with each supplier’s name.\n\nPostgreSQL does joins natively.\n\nOpenSearch is a search engine, excellent at literal and hybrid retrieval, but it does not do relational joins.\n\nThey are not interchangeable, and neither is replaced by a SearchVectors call.\n\nSeveral practitioners raised fair objections in the launch discussion. One noted that OpenSearch is frequently among the most expensive data stores in an AWS estate and that schema changes on a large cluster are painful.\n\nBoth observations are accurate, and neither makes DynamoDB a drop-in substitute for a search engine.\n\nThe sharpest pushback came from someone running a self-managed MongoDB cluster: five substantial nodes, 2 TB of data, about $1,400 per month, with a DynamoDB migration estimated above $15,000.\n\nThe counterargument arrived immediately and is equally valid: what does the engineer maintaining that cluster cost, and what availability, durability, and tail latency does it actually deliver?\n\nBoth sides are right, which is precisely why this is an architecture decision and not a price lookup.\n\nIf you already run reliable infrastructure and employ the people to keep running it, the premium you pay AWS to operate the thing for you buys you less. If your alternative is turning a small product team into a part-time database operations group, it buys you a great deal.\n\nThe genuinely new option is narrower and more useful than the headline suggests: you can now add similarity search to an application whose data already lives in DynamoDB, without standing up a second database and without maintaining a synchronization pipeline to keep the two copies aligned.\n\nThat pipeline was never the interesting part of anyone’s architecture, and it broke often enough to matter. Deleting it is the real win.\n\nTake this path if your data already lives in DynamoDB, your table uses on-demand capacity or can reasonably move to it, you can name a partition key today that both matches your query scope and holds a real population of vectors per value, your filters are exact-match or can be bucketed into exact matches, and either your tenants do not require data-layer isolation or you are willing to give each one its own table or index. Under those conditions this beats the alternative comfortably, because the alternative means a second database and a synchronization pipeline you would rather not own.\n\nLook elsewhere if you need range filters or hybrid keyword-and-semantic retrieval, if your indexed data is large and cold and your query volume is modest, which is the S3 Vectors profile, if your access pattern requires searching all of it at once, or if strict multi-tenant isolation at the IAM layer is non-negotiable.\n\nWhichever way you lean, measure three things before committing.\n\nTrack VectorSearchRequestBytes and VectorWriteRequestBytes against your real data and query mix, because they replace every estimate in this post with a number from your own workload.\n\nMeasure actual propagation lag between writing a vector and finding it.\n\nAnd test **p99** search latency while ordinary key-value traffic runs against the same table at production volume.\n\nThe p99, or 99th percentile, is the time within which 99 out of 100 requests complete, which makes it a measure of your worst hundredth rather than your typical case.\n\nAverages hide that request entirely, and it is the one the user notices and complains about, which is why it is the number worth watching. Test it under mixed load because vector search shares the table’s underlying infrastructure and mixed-workload behavior under load is the one variable nobody has published numbers for.\n\nWhatever you find there will tell you more than any launch post, including this one.\n\n*I publish every week at buildwithaws.substack.com. Subscribe. It's free.*", "url": "https://wpnews.pro/news/dynamodb-now-does-vector-search", "canonical_source": "https://dev.to/aws-builders/dynamodb-now-does-vector-search-4hld", "published_at": "2026-08-18 16:57:51+00:00", "updated_at": "2026-08-18 17:13:23.978747+00:00", "lang": "en", "topics": ["artificial-intelligence", "machine-learning"], "entities": ["AWS", "DynamoDB", "MongoDB", "S3"], "alternates": {"html": "https://wpnews.pro/news/dynamodb-now-does-vector-search", "markdown": "https://wpnews.pro/news/dynamodb-now-does-vector-search.md", "text": "https://wpnews.pro/news/dynamodb-now-does-vector-search.txt", "jsonld": "https://wpnews.pro/news/dynamodb-now-does-vector-search.jsonld"}}