Intermedio14 min de lectura

Búsqueda vectorial en DynamoDB

DynamoDB ganó búsqueda vectorial nativa el 5 de agosto de 2026. Guardas los embeddings como una List normal de valores Number en tus Items, añades un índice vectorial y ejecutas consultas de vecinos más cercanos aproximados con la nueva API SearchVectors.

Hasta ahora, la búsqueda por similitud significaba replicar tu tabla en OpenSearch o en una base de datos vectorial aparte y mantener las dos sincronizadas. Ese pipeline desapareció. El modelo de facturación que lo reemplaza no se parece a nada más en DynamoDB.

¿DynamoDB admite la búsqueda vectorial?

Sí — de forma nativa, desde el 5 de agosto de 2026. Guardas los embeddings como una List normal de valores Number, añades un índice vectorial y ejecutas consultas de vecinos más cercanos aproximados con la API SearchVectors — sin réplica en OpenSearch y sin base de datos vectorial aparte. Solo funciona en tablas bajo demanda, hasta 4,096 dimensiones, y se factura por byte escrito, buscado y almacenado.

  • Una tercera familia de índices: los índices vectoriales se sientan junto a los y los LSI. Una nueva API de lectura (SearchVectors), solo ANN, solo tablas bajo demanda, hasta 4,096 dimensiones.
  • Es rápido, y medido: contra nuestro índice vivo de 1024 dimensiones en us-east-1, SearchVectors respondió tan rápido como GetItem desde el mismo cliente (p50 de 39 ms frente a 44 ms), y una escritura fresca se volvió buscable en ~136 ms.
  • La medición es por byte: $0.52 por GB de escrituras vectoriales, $0.002 por GB de datos vectoriales que examina una búsqueda, $0.25 por GB-mes de almacenamiento (us-east-1). Indexar un embedding hace que su copia en la tabla base facture exactamente 4 bytes por dimensión; la misma lista sin indexar factura ~1.9×.
  • S3 Vectors sigue siendo el almacén masivo: aproximadamente 8× más barato en reposo y mucho más barato para cargar en lote. DynamoDB gana en lecturas de milisegundos, escrituras en streaming y vectores que viven junto al Item que describen.

Cómo funciona un índice vectorial

No hay un tipo de atributo nuevo. Un embedding es una lista ordinaria de números en el Item, {"L": [{"N": "0.0132"}, {"N": "-0.0475"}, …]} en el cable, escrita con los mismos PutItem y UpdateItem que ya usas.

El índice es una estructura aparte. DynamoDB replica el vector en él de forma asíncrona con precisión float de 32 bits, junto con los atributos que proyectas o por los que filtras. Los resultados de búsqueda son de consistencia eventual, como una lectura de .

El desfase es pequeño en la práctica. Contra nuestro índice de prueba vivo, un vector recién escrito apareció en los resultados de búsqueda unos 136 ms después de que el PutItem retornara. Aun así, nunca construyas sobre él un flujo de leer-tus-propias-escrituras.

replicación async, f32PutItem / UpdateItemTabla baseembedding como List de NumberÍndice vectorialvectores + atributos de filtroSearchVectorsTopK + filtros de igualdadTop-K Items con puntuación

Dónde se sitúa junto a los tipos de índice que ya conoces:

Índice vectorialGSILSI
Máximo por tabla5205
API de lecturaSearchVectorsQuery, ScanQuery, Scan
PartiQLNo
Modo de capacidadSolo bajo demandaAmbosAmbos
ConsistenciaEventualEventualFuerte disponible
Añadir tras crear la tablaNo

Cada índice fija su número de dimensiones (hasta 4,096) y una de tres funciones de distancia al crearse. COSINE y EUCLIDEAN puntúan más-bajo-es-más-similar; DOT_PRODUCT puntúa más-alto-es-más-similar y puede ser negativo. Nada de eso puede cambiarse después.

Una nota de precisión antes de que hagas benchmark de nada. El índice guarda los vectores a f32; los valores de mayor precisión se aceptan, pero pierden precisión al entrar. Si llegas con embeddings float64, cada distancia se computa contra la copia f32, así que mide el recall contra f32, no contra tus originales.

Crea uno y busca en él

Supón que haces búsqueda semántica sobre tickets de soporte, para que un agente pueda encontrar «clientes que ya se toparon con esto antes» sin coincidir palabras clave. Cada Item de ticket lleva un embedding de su asunto y su cuerpo, generado por el modelo que quieras (Titan Text Embeddings V2 cuesta $0.02 por millón de tokens de entrada en Bedrock).

Añade el índice a la tabla existente. El elemento HASH acota cada búsqueda a un solo valor de product; los atributos INLINE_FILTER (hasta 18) permiten filtros de igualdad en el momento de la búsqueda:

aws dynamodb update-table \
  --table-name SupportTickets \
  --attribute-definitions AttributeName=product,AttributeType=S \
                          AttributeName=severity,AttributeType=S \
  --vector-index-updates '[{"Create": {
    "IndexName": "TicketEmbeddings",
    "VectorAttribute": {"AttributeName": "embedding"},
    "SearchSchema": [
      {"AttributeName": "product", "SearchSchemaElementType": "HASH"},
      {"AttributeName": "severity", "SearchSchemaElementType": "INLINE_FILTER"}
    ],
    "Projection": {"ProjectionType": "KEYS_ONLY"},
    "Dimensions": 1024,
    "DistanceFunction": "COSINE"
  }}]'

La construcción se comporta como un backfill de GSI con bordes más afilados. SearchVectors devuelve ValidationException durante toda la construcción, sin resultados parciales.

AWS advierte de que el endpoint de búsqueda puede seguir rechazando un rato incluso después de que DescribeTable diga ACTIVE. No hay waiter; sondea con una búsqueda real en un bucle de reintentos. Cuando creamos el índice junto con una tabla vacía, pasó a ACTIVE en 26 segundos y aceptó búsquedas 0.6 s después.

La búsqueda toma el embedding de la consulta como un array JSON pelado de valores {"N": …}. No lo envuelvas en una L de DynamoDB. El atributo guardado usa el tipo lista, el parámetro de la solicitud no, y confundirlos es un primer error fácil:

aws dynamodb search-vectors \
  --table-name SupportTickets \
  --index-name TicketEmbeddings \
  --search-vector file://query-embedding.json \
  --top-k 5 \
  --search-condition-expression "product = :p AND severity = :sev" \
  --expression-attribute-values '{":p": {"S": "checkout"}, ":sev": {"S": "high"}}'

Recibes de vuelta hasta TopK Items ordenados del más similar al menos, cada uno con un Score, más ConsumedCapacity cuando lo pides. TopK tiene tope en 100, no hay paginación y la respuesta tiene tope en 16 MB.

El embedding mismo queda excluido de los resultados a menos que lo proyectes y lo pidas. Ese comportamiento por defecto es deliberado; devolver vectores infla tanto la respuesta como la factura de búsqueda.

Las expresiones de filtro solo aceptan igualdad, sin BETWEEN, IN ni begins_with. Cuando el índice define un atributo HASH, cada búsqueda debe fijar exactamente un valor para él. La formulación de AWS sobre los operadores de rango es "not yet available", así que esto puede relajarse.

Conviene conocer dos sorpresas operativas antes del primer despliegue. SearchVectors necesita la nueva acción IAM dynamodb:SearchVectors, que ninguna de tus políticas de lectura existentes incluye.

También habla con un endpoint aparte, search-dynamodb.{region}.amazonaws.com. Las listas de permitidos de salida y las configuraciones de VPC endpoint que solo cubren dynamodb.{region} rompen únicamente la búsqueda vectorial, con un error de conexión que nunca dice por qué.

Qué factura un índice vectorial

Tres medidores nuevos, todos por byte, con un mínimo de 1 KB por escritura y por solicitud de búsqueda, encima de los cargos normales de la tabla (us-east-1, de la API de precios de AWS, 2026-08-15):

MedidorStandardStandard-IA
Escrituras vectoriales$0.52/GB$0.65/GB
Datos vectoriales examinados por búsqueda$0.002/GB$0.0025/GB
Almacenamiento (tabla e índice)$0.25/GB-mes$0.10/GB-mes

La documentación advierte de que la copia en la tabla base de un embedding, guardada como cadenas decimales dentro de una List, puede ser "considerably larger" que la copia f32 del índice. Medimos la facturación en unidades de escritura contra tablas vivas en us-east-1, y la verdad es más extraña.

Un embedding en un atributo sin índice vectorial factura la regla decimal documentada, aproximadamente 1.9× el tamaño f32. Apunta un índice vectorial a ese mismo atributo y su facturación en la tabla base cae a exactamente 4 bytes por dimensión:

DimensionesAtributo List sin indexar (facturado)Mismo atributo, con índice vectorial (facturado)
2561,914 B1,024 B
7685,760 B3,072 B
1,0247,653 B4,096 B
1,53611,501 B6,144 B
3,07222,957 B12,288 B

Medido bisecando la frontera de unidades de escritura con un atributo de relleno, con clave de Item fresca por escritura, calibrado al byte. Nuestro Item de ticket completo de 1024 dimensiones facturó 5 unidades de escritura; el Item idéntico sin índice sobre embedding factura 8.

El medidor de escrituras vectoriales siguió de cerca el tamaño f32 en las mismas ejecuciones. VectorWriteRequestBytes volvió como 4 bytes por dimensión más 11 B de overhead de clave en un índice pelado, y más 65 B con nuestro search schema de dos atributos.

La facturación de búsqueda es el medidor que no puedes computar por adelantado. VectorSearchRequestBytes sigue cuántos datos vectoriales examinó el recorrido ANN, y la propia recomendación de AWS es medirlo con ReturnConsumedCapacity en lugar de estimarlo a partir del número de dimensiones.

Nuestra sonda da los primeros puntos de datos. TopK=10 sobre una partición de 50 vectores examinó 22.2-22.4 KB por búsqueda; la misma búsqueda sobre una partición de 1 vector examinó aun así 21.4 KB, así que a pequeña escala hay un suelo de aproximadamente 21 KB (unos $0.00000004) por consulta. El tutorial de AWS reporta 31,449 bytes para su propio ejemplo de 50 vectores.

Modela los costes del lado de la tabla en la calculadora de precios; los medidores vectoriales se apilan encima de las unidades de escritura que ya computa.

Búsqueda vectorial de DynamoDB frente a S3 Vectors

AWS ahora vende dos almacenes vectoriales serverless, y están construidos para patrones de acceso opuestos. S3 Vectors (GA en diciembre de 2025) guarda hasta 2 mil millones de vectores por índice a $0.06/GB-mes, responde en el rango de 100 ms a 1 s, y factura cada consulta contra el tamaño de todo el índice.

DynamoDB responde en milisegundos y factura contra lo que la búsqueda examina, no contra lo que el índice guarda.

Búsqueda vectorial de DynamoDBS3 Vectors
GAAgo 2026Dic 2025
Clase de latenciams de un solo dígito (afirmación de AWS)~100 ms frecuente, sub-1 s infrecuente (afirmación de AWS)
Techo de escalaSin tope declarado de vectores; tope de tabla de 600 GB para crear el índice (soft)2 mil millones de vectores por índice
Dimensiones máx.4,0964,096
Funciones de distanciaCoseno, euclidiana, producto escalarCoseno, euclidiana
Escrituras al índiceAsync desde la tabla (consistencia eventual)Fuertemente consistentes
FiltradoSolo igualdad, ≤18 atributos + 1 clave de particiónFiltros de metadatos ricos, tope filtrable de 2 KB por vector
TopK100, sin paginación10,000, paginado
Almacenamiento$0.25/GB-mes, dos veces (tabla + índice)$0.06/GB-mes, una vez
Escrituras$0.52/GB, mín. 1 KB/solicitud$0.20/GB, mín. 128 KB/PUT
Consultas$0.002/GB examinado$2.50/M solicitudes + cargo por bytes procesados de todo el índice

Los mínimos de escritura deciden el caso de streaming, y apuntan en dirección opuesta a las tarifas de almacenamiento. Escribiendo un vector de 1024 dimensiones cada vez, por millón de escrituras (con las tarifas verificadas y nuestras 5 unidades de escritura + 4,161 bytes de escritura vectorial medidos por Item):

Patrón de escrituraDynamoDBS3 Vectors
Escrituras de un solo vector~$5.14/M~$24.41/M
En lote (500 por PutVectors)n/a (las escrituras son por Item)~$0.78/M

El mínimo de 128 KB por PUT de S3 lo convierte en la opción cara para exactamente la carga de trabajo para la que la gente supone que es barato. Envía vectores de uno en uno a S3 Vectors y pagas casi 5× la tarifa de DynamoDB; cárgalos en lote y pagas aproximadamente 7× menos.

Totales mensuales de almacenamiento y consultas para un corpus de 1024 dimensiones con 1M de consultas al mes, computados con las tarifas verificadas (los costes de escritura son la tabla por millón de arriba). El cargo por consulta de S3 Vectors sigue su fórmula publicada, el tamaño de todo el índice por una tarifa escalonada.

El cargo por consulta de DynamoDB depende de los bytes examinados, así que mostramos un rango de sensibilidad en lugar de fingir que conocemos tu recorrido:

CorpusAlmacenamiento DynamoDBConsultas DynamoDB (4 / 40 / 400 MB examinados)Almacenamiento S3 VectorsConsultas S3 Vectors
1M de vectores~$1.95$8 / $80 / $800~$0.23~$11
10M de vectores~$19.50$8 / $80 / $800~$2.35~$80
100M de vectores~$195$8 / $80 / $800~$23.50~$217

De esa tabla salen dos cosas. El coste por consulta de DynamoDB no crece con el tamaño del corpus — una búsqueda ANN examina un vecindario, no el índice, y acotar por clave de partición lo encoge aún más.

La ventaja de almacenamiento de S3 Vectors (~8×, ya que DynamoDB guarda dos copias f32 a 4× la tarifa) se acumula para siempre, consulte alguien o no.

Cuándo usar cada uno

  • Los vectores describen Items vivos que ya guardas en DynamoDB (tickets, productos, sesiones de usuario, memoria de agentes): usa el índice vectorial. Una sola ruta de escritura, un solo Item, sin pipeline de sincronización que derive.
  • Millones de embeddings, consultados de vez en cuando (RAG sobre documentos, archivos, trabajos nocturnos): usa S3 Vectors. Carga en lote barato, paga $0.06/GB en reposo, tolera unos cientos de ms.
  • QPS alto con ranking híbrido (relevancia de texto + vectores, facetado, agregaciones): OpenSearch sigue siendo la respuesta, con un suelo de infraestructura de aproximadamente $350/mes para una colección serverless clásica.
  • Vectores unidos a datos relacionales: Aurora PostgreSQL con pgvector, que escala a cero y queda por debajo de ~$50/mes para cargas de trabajo RAG pequeñas.

El valor por defecto honesto para una casa DynamoDB es usar los dos. Mantén los vectores calientes y filtrables en la tabla, donde las escrituras son atómicas con el Item, y archiva la cola larga en S3 Vectors, cuyas escrituras en lote fuertemente consistentes lo hacen un sumidero limpio.

Las trampas

  • Des-indexado silencioso: un Item al que le falta el atributo HASH del índice se escribe en la tabla sin problema y nunca entra al índice vectorial. Lo reprodujimos en vivo: el PutItem tuvo éxito, y el vector estaba ausente de todas las particiones 15 segundos después. Sin error, sin resultado, nada en la respuesta que te avise.
  • Las escrituras con dimensiones equivocadas se rechazan: cambia de modelo de embeddings sin migrar y cada escritura falla con una ValidationException que nombra el atributo y los dos tamaños (Invalid size for parameter, recogida literalmente en su propia página), ya que el índice fija el número de dimensiones para siempre.
  • Embeddings caducados: DynamoDB nunca recomputa vectores. Edita el texto de un ticket sin reescribir embedding y las búsquedas coinciden en silencio con el contenido viejo. Streams más un consumidor de regeneración es el arreglo estándar.
  • TopK siempre devuelve K Items: con tres buenas coincidencias y --top-k 10, igual recibes 10. Juzga la relevancia por Score, no por el número de resultados, y recuerda que la dirección de la puntuación se invierte entre funciones de distancia.
  • Los mínimos de 1 KB: los vectores de pocas dimensiones no se miden proporcionalmente más baratos, ni en escrituras ni en búsquedas.
  • Todo es inmutable: las dimensiones, la función de distancia y el conjunto de atributos de una proyección INCLUDE requieren borrar y recrear para cambiar. El almacenamiento del índice factura durante toda la vida del índice, se consulte o no.

Pruébalo con tus propias tablas

La búsqueda vectorial hereda la disciplina de costes que el resto de DynamoDB te enseñó. Dimensiona el embedding antes de comprometerte con él, porque los límites de tamaño de Item siguen aplicando y un embedding de 3072 dimensiones añade 12 KB a cada escritura del Item en ambos medidores.

La mecánica del índice te resultará familiar si sabes cómo los GSI se replican de forma asíncrona y cuándo elegir un GSI en lugar de un LSI. Para búsqueda léxica sobre los mismos datos, DynamoDB sigue sin tener motor de búsqueda de texto completo; la búsqueda vectorial coincide por significado, no por ortografía.

Comprueba el coste real en bytes de un embedding en la calculadora de tamaño de Item, y luego prueba DynoTable para explorar los Items detrás de tu índice vectorial — los embeddings se renderizan como atributos de lista ordinarios justo al lado de los campos por los que filtras.

Actualizado