Turbopuffer, la base de datos vectorial serverless que usan Cursor y Notion, publicó el 30 de septiembre de 2026 un artículo titulado "RIP, vector database" en el que anuncia que su arquitectura interna deja de girar alrededor del índice vectorial.
La compañía está migrando a turbopuffer v3, una reescritura que convierte el índice ANN, el que hace la búsqueda por similitud, en "uno más" de varios índices secundarios, en vez del eje central del sistema. Es el caso perfecto para entender, de punta a punta, cómo se diseña el almacenamiento de una base de datos vectorial moderna.
TL;DR
- El 30 de septiembre de 2026 turbopuffer anunció que el índice ANN deja de ser el eje de su almacenamiento.- Object storage es la fuente de verdad; un caché en niveles de NVMe y memoria responde las consultas rápido.- SPANN y SPFresh agrupan vectores en un árbol de clusters jerárquico en vez de un grafo como HNSW.- El diseño vector-primario frenaba consultas como GROUP BY y agregaciones sobre los mismos datos.- Cursor, Notion y el motor de sincronización de Linear ya corren sobre esta arquitectura serverless.
¿Qué es una base de datos vectorial serverless?
Una base de datos vectorial es un sistema que guarda representaciones numéricas (embeddings) de texto, imágenes o audio y responde consultas por similitud, no por igualdad exacta. La variante serverless guarda esos datos en object storage barato y asigna cómputo bajo demanda, sin servidores fijos que mantener ni administrar.
Cursor y Notion corren sobre turbopuffer desde su lanzamiento como base vectorial serverless.
Por qué importa
Durante años, montar una base de datos vectorial significaba levantar un clúster propio: dimensionar memoria para el índice HNSW, replicarlo y pagar por capacidad reservada aunque el tráfico fuera intermitente. El modelo serverless invierte esa ecuación: los datos quedan en object storage barato, el mismo tipo de almacenamiento que usa S3, y el cómputo se asigna solo cuando llega una consulta.
Esa separación entre almacenamiento y cómputo es la misma que adoptaron los data warehouses modernos como Snowflake o BigQuery, aplicada ahora a vectores. El resultado es que un namespace casi inactivo cuesta casi nada, porque guardar un vector en object storage es órdenes de magnitud más barato que mantenerlo cargado en la memoria de un clúster dedicado.
Esto importa en particular para aplicaciones de RAG (retrieval-augmented generation) y agentes de IA, donde cada usuario, documento o conversación puede necesitar su propio namespace aislado. Mantener miles de namespaces pequeños vivos en memoria todo el tiempo no es viable económicamente; servirlos bajo demanda desde object storage sí lo es.
Cómo funciona por dentro
Object storage como fuente de verdad
En turbopuffer, cada namespace, la unidad lógica donde viven los documentos de un cliente, se guarda como un conjunto de archivos inmutables en object storage. Cuando el cliente escribe nuevos vectores, el sistema no los actualiza en el lugar: crea un archivo nuevo y lo agrega al namespace, de forma parecida a como Git agrega commits en vez de reescribir el historial.
Esta inmutabilidad es la que hace posible el modelo de costos serverless. Object storage no cobra por mantener un servidor encendido, solo por los gigabytes guardados y por las operaciones de lectura y escritura. Pero tiene una contrapartida: la latencia de una lectura directa a object storage se mide en decenas o cientos de milisegundos, demasiado lenta para servir una búsqueda interactiva.
Caché en niveles: NVMe y memoria
Para resolver el problema de latencia, turbopuffer agrega dos niveles de caché entre el cliente y object storage: un nivel de memoria RAM, el más rápido pero el más caro y limitado, y un nivel de SSD NVMe, más lento que la RAM pero mucho más barato y con capacidad para guardar namespaces enteros que no caben en memoria.
Cuando llega una consulta, el motor primero busca los datos en memoria. Si no están, un "cache miss", busca en NVMe. Si tampoco están ahí, recién entonces lee desde object storage y, de paso, promueve esos datos a los niveles de caché superiores para que la próxima consulta sea más rápida. Es el mismo principio que usa una CPU con sus niveles L1, L2 y L3, aplicado a un sistema distribuido.
flowchart TD
A["Cliente"] --> B["Motor de consultas de turbopuffer"]
B --> C["Cache en memoria"]
C --> D["Cache NVMe"]
D --> E[("Object storage: fuente de verdad")]
subgraph "Niveles de cache"
C
D
end
sequenceDiagram
participant C as Cliente
participant Q as Motor de consultas
participant M as Cache en memoria
participant N as Cache NVMe
participant O as Object storage
C->>Q: consulta top_k=10
Q->>M: busca en cache caliente
alt dato en memoria
M-->>Q: devuelve resultado
else fallo de cache
Q->>N: busca en NVMe
alt dato en NVMe
N-->>Q: devuelve resultado
else fallo total
Q->>O: lee desde object storage
O-->>Q: devuelve datos
end
end
Q-->>C: responde resultado final
Cómo se indexan los vectores: SPANN y SPFresh
Para la búsqueda por similitud, turbopuffer no usa un índice basado en grafos como HNSW, el que usan la mayoría de bases vectoriales self-hosted. Usa un índice de clustering jerárquico, basado primero en SPANN y después migrado a SPFresh para soportar indexación incremental sin reconstruir todo el árbol en cada escritura.
flowchart TD
R["Centroide raíz"] --> L1["Centroide hoja 1"]
R --> L2["Centroide hoja 2"]
R --> L3["Centroide hoja 3"]
L1 --> V1["Vector C0L0"]
L1 --> V2["Vector C0L1"]
L2 --> V3["Vector C1L0"]
L2 --> V4["Vector C1L1"]
L3 --> V5["Vector C2L0"]
L3 --> V6["Vector C2L1"]
La idea es agrupar los vectores en clusters, agrupar los centroides de esos clusters en clusters de nivel superior y repetir el proceso hasta llegar a una sola raíz. Un grafo tipo HNSW es difícil de partir en archivos independientes porque cualquier nodo puede conectar con cualquier otro; un árbol de clusters sí se presta a vivir en archivos separados en object storage, porque cada rama es relativamente independiente de las demás.
Cada vector queda identificado por lo que turbopuffer llama una "dirección ANN": un ClusterId que indica a qué grupo pertenece y un LocalId que lo identifica dentro de ese grupo. En las primeras dos versiones de turbopuffer, esa dirección ANN era literalmente la clave primaria de todo el sistema: los demás índices, filtros de atributos, búsqueda de texto, apuntaban a direcciones ANN, no a IDs de documento.
De v1 a v3: la evolución de turbopuffer
v1: solo un ID y un vector
turbopuffer nació como una base de datos vectorial serverless pura: cada documento era apenas un ID y un vector. Toda la arquitectura, desde el formato de archivo hasta el plan de consultas, giraba en torno al árbol de clustering SPANN/SPFresh descrito arriba. Esa especialización es lo que le permitió ofrecer precios bajos: al no cargar con la generalidad de una base relacional, podía optimizar cada byte guardado en object storage específicamente para la búsqueda por similitud.
v2: filtros de atributos y búsqueda de texto completo
La demanda de los clientes forzó la primera ampliación: poder filtrar una búsqueda vectorial por atributos, por ejemplo "vectores similares a esta consulta, pero solo del usuario X". turbopuffer resolvió esto con un índice invertido clásico, el mismo tipo de estructura que usan los motores de búsqueda de texto: una clave de atributo-valor apunta a la lista de direcciones ANN que lo contienen.
Con la misma lógica llegó la búsqueda de texto completo con ranking BM25: por cada término, el índice guarda la lista de documentos que lo contienen junto con la frecuencia del término y la longitud del documento, los dos datos que BM25 necesita para puntuar relevancia. A partir de ahí, turbopuffer sumó agregaciones, búsqueda por regex, fuzzy matching y vectores dispersos, todos construidos sobre el mismo layout con el índice ANN como primario.
El problema de tener un índice vectorial como primario
El propio turbopuffer admite que ese diseño funcionó muy bien para lo que fue pensado: búsqueda por similitud rápida y barata. Pero con el tiempo se volvió una camisa de fuerza para todo lo demás. Consultas como GROUP BY o agregaciones sobre atributos, habituales en SQL, encajan mal cuando la estructura de almacenamiento de fondo está optimizada para vecinos más cercanos, no para agrupar filas por una columna.
La razón es estructural: si cada índice secundario apunta a una dirección ANN, cualquier operación que no pase primero por el árbol de clustering tiene que reconstruir, de forma indirecta, la relación entre documentos. Es el equivalente a tener que consultar siempre el índice de un libro para encontrar una página, incluso cuando ya se sabe el número de capítulo.
v3: el índice ANN pasa a ser secundario
La solución que turbopuffer empezó a implementar el 30 de septiembre de 2026 invierte la jerarquía: la compañía está migrando hacia un índice primario más flexible, separado del árbol de clustering vectorial, y convierte el ANN en un índice secundario más, al mismo nivel que el filtro de atributos o la búsqueda de texto.
📌 Nota: turbopuffer todavía está en pleno proceso de esa migración y lo está documentando en público, artículo por artículo, así que el diseño final del índice primario de v3 no está cerrado todavía.
Lo que sí confirma el anuncio es el objetivo: que el mismo almacenamiento sirva mejor tanto a la búsqueda vectorial como a consultas de tipo SQL, sin que una le quite eficiencia a la otra.
SPANN y SPFresh organizan los vectores en árboles de clusters, no en grafos tipo HNSW.
Ejemplos prácticos y cómo empezar
turbopuffer es un servicio administrado, no un paquete que se instala localmente, pero sí tiene clientes oficiales en Python, TypeScript y Go que funcionan igual en Windows, macOS y Linux porque hablan con la API sobre HTTPS. Para seguir estos ejemplos hace falta una cuenta y una API key desde turbopuffer.com.
pip install turbopuffer
Este comando instala el cliente oficial de Python y funciona igual en Windows, macOS o Linux porque es un paquete puro sobre HTTPS, sin dependencias nativas que compilar.
import os
import turbopuffer as tpuf
tpuf.api_key = os.environ["TURBOPUFFER_API_KEY"]
ns = tpuf.Namespace("documentos-demo")
ns.upsert(
ids=[1, 2],
vectors=[[0.12, 0.98, 0.33], [0.45, 0.21, 0.88]],
attributes={
"titulo": ["Introduccion a RAG", "Busqueda semantica"],
"idioma": ["es", "es"],
},
)
Este bloque crea, o reutiliza, el namespace documentos-demo y sube dos vectores de 3 dimensiones con sus atributos. En un caso real los vectores vendrían de un modelo de embeddings y tendrían cientos de dimensiones, no tres.
ns.query(
vector=[0.10, 0.95, 0.30],
top_k=2,
filters=("idioma", "Eq", "es"),
)
Esta llamada busca los 2 vectores más cercanos al vector de consulta, pero solo entre los documentos en español. Devuelve una lista de resultados ordenados por distancia. La salida esperada, de forma resumida y con nombres de campo que pueden variar según la versión del cliente, se parece a esto:
[
{"id": 2, "dist": 0.04, "attributes": {"titulo": "Busqueda semantica"}},
{"id": 1, "dist": 0.11, "attributes": {"titulo": "Introduccion a RAG"}}
]
Para confirmar que el namespace existe y cuántos vectores tiene, turbopuffer expone un dashboard web en turbopuffer.com además de un endpoint de metadata. No hay forma directa de pegar acá la respuesta exacta de ese endpoint porque el formato cambia entre versiones del cliente; lo más confiable es revisar la documentación oficial antes de automatizar un chequeo contra campos específicos.
💡 Tip: si tu aplicación crea un namespace por usuario o por conversación, un patrón común en RAG, el modelo serverless es la diferencia entre pagar por miles de clústeres inactivos y pagar casi nada por los namespaces que nadie consulta esta semana.
Casos de uso reales
Cursor, el editor de código con IA, usa turbopuffer para indexar y buscar sobre bases de código completas en tiempo real. Notion lo usa para búsqueda semántica entre documentos de sus usuarios. Ninguno de los dos es un caso de laboratorio: ambos corren en producción con tráfico real y namespaces que crecen todos los días.
El caso más interesante para entender hacia dónde va turbopuffer v3 es Linear, que usa el sistema para algo que no es búsqueda: su motor de sincronización en tiempo real entre el cliente y el servidor. Ese uso "no-search" es exactamente lo que el diseño vector-primario de v1 y v2 no facilitaba, y es parte de la motivación detrás del rediseño hacia un índice primario flexible.
Errores comunes y buenas prácticas
- Tratarla como una base relacional de propósito general, está optimizada para object storage y consultas de similitud; forzar joins complejos o transacciones multi-tabla no es su punto fuerte.- Ignorar el calentamiento del caché, un namespace que no se consulta hace tiempo vive solo en object storage; la primera consulta tras un período de inactividad va a ser más lenta porque tiene que subir los datos a NVMe y memoria antes de responder rápido.- Filtrar por atributos de alta cardinalidad sin medir el impacto, el índice invertido funciona mejor con un número manejable de valores distintos; un atributo tipo user_id con millones de valores únicos genera listas de postings muy fragmentadas.- Subestimar el costo de las lecturas a object storage, el almacenamiento en sí es barato, pero cada operación de lectura tiene un costo propio; un patrón de consulta que ignora el caché y pega siempre contra el nivel frío puede salir más caro de lo esperado.- No separar namespaces por cliente cuando el caso de uso lo pide, el aislamiento por namespace es lo que permite escalar a miles de clientes sin que uno afecte la latencia de otro; mezclar todo en un namespace gigante reduce esa ventaja.
Comparativa con alternativas
No toda aplicación necesita un motor de búsqueda vectorial serverless dedicado. La siguiente tabla compara las opciones más comunes en 2026.
OpciónCuándo usarlaVentajaLimitaciónServerless sobre object storage (turbopuffer)Muchos namespaces con tráfico intermitente, RAG multi-tenant, agentesCosto casi nulo en reposo, escala a miles de namespacesLatencia en frío más alta que un índice siempre en memoriapgvector (extensión de PostgreSQL)Ya hay datos relacionales y el volumen de vectores es moderadoUn solo motor para SQL y vectores, sin sistema nuevo que operarEl índice vive en el propio clúster de Postgres: escalar mucho implica escalar todoMotor self-hosted con HNSW (tipo Qdrant, Weaviate)Baja latencia constante y control total de la infraestructuraSiempre caliente, sin calentamiento de cachéHay que dimensionar y pagar el clúster aunque el tráfico sea bajoFAISS embebido en la aplicaciónPrototipos y datasets chicos que caben en memoria de un procesoCero infraestructura externa, control total en el propio procesoNo es distribuido ni persistente por sí mismo
Profundizando
La decisión de usar clustering jerárquico, SPANN y SPFresh, en vez de un grafo HNSW no es solo una preferencia técnica: es lo que hace viable guardar el índice en object storage. Un grafo HNSW necesita saltar de nodo en nodo siguiendo punteros que pueden estar en cualquier parte del archivo; eso es rápido en memoria pero carísimo si cada salto implica una lectura a un sistema con cientos de milisegundos de latencia. Un árbol de clusters, en cambio, se recorre nivel por nivel, y cada nivel se puede guardar como un rango contiguo de claves ordenadas.
Eso explica también por qué turbopuffer modela su almacenamiento como un mapa clave-valor ordenado y único, con claves compuestas por ClusterId y LocalId. Una clave ordenada permite usar range scans eficientes: pedir "todos los vectores del cluster 7" es, en términos de almacenamiento, pedir un rango contiguo de claves, no una búsqueda dispersa.
El cambio hacia v3 generaliza esa misma idea de clave ordenada, pero sin asumir que el ANN tiene que ser la raíz de esa jerarquía. Si la clave primaria pasa a ser, por ejemplo, el ID del documento en vez de su dirección ANN, agrupar por atributo o hacer un GROUP BY deja de requerir pasar primero por el árbol de clustering vectorial. El índice ANN se convierte en un índice secundario que apunta hacia esa clave primaria, exactamente al revés de cómo funcionaba en v1 y v2.
📖 Resumen en Telegram: Ver resumen
Tu próximo paso: creá una cuenta gratuita en turbopuffer.com, subí 50 vectores de un dataset de prueba con el cliente de Python y corré una consulta con un filtro de atributo para ver en la práctica la diferencia entre el índice ANN y el índice invertido.
Preguntas frecuentes
¿Qué es una base de datos vectorial serverless y en qué se diferencia de pgvector?
Ambas resuelven búsqueda por similitud, pero una base de datos vectorial serverless como turbopuffer guarda los datos en object storage y escala el cómputo por consulta, mientras pgvector corre dentro de una instancia de PostgreSQL que hay que dimensionar y mantener encendida todo el tiempo.
¿Por qué turbopuffer no usa un índice HNSW como la mayoría de motores vectoriales?
Porque un grafo HNSW no se presta bien a vivir fragmentado en archivos de object storage: cada salto entre nodos puede terminar en cualquier parte del índice. El árbol de clustering de SPANN y SPFresh se recorre nivel por nivel y se guarda como rangos ordenados, algo mucho más amigable con almacenamiento de objetos.
¿Qué cambia exactamente turbopuffer v3 respecto a v2?
v2 usaba la dirección ANN, ClusterId y LocalId, como clave primaria de todo el sistema, y los demás índices apuntaban a esa dirección. v3 separa esa relación: el índice ANN pasa a ser secundario, como el de atributos o el de texto completo, en vez de ser el eje de todo el almacenamiento.
¿Sirve un motor de búsqueda vectorial serverless para algo que no sea búsqueda?
Sí. Linear lo usa como motor de sincronización en tiempo real entre cliente y servidor, no para buscar. Es justamente el tipo de caso de uso que el rediseño de v3 busca facilitar, al dejar de forzar todo a través del índice vectorial.
¿Qué pasa con la latencia de turbopuffer cuando un namespace lleva tiempo sin usarse?
Si los datos solo viven en object storage porque ningún nivel de caché los tiene cargados, la primera consulta va a tardar más mientras el sistema promueve esos datos a NVMe y memoria. Las consultas siguientes sobre el mismo namespace son más rápidas porque ya quedaron en caché.
Referencias
- Turbopuffer: "RIP, vector database": el anuncio original de la migración a v3, publicado el 30 de septiembre de 2026.- Documentación oficial de turbopuffer: referencia de API, clientes y modelos de precios.- Wikipedia: Vector database: definición general y contexto histórico del concepto.- FAISS en GitHub: biblioteca de referencia para búsqueda por similitud y construcción de índices ANN.
📱 ¿Te gusta este contenido? Únete a nuestro canal de Telegram @programacion donde publicamos a diario lo más relevante de tecnología, IA y desarrollo. Resúmenes rápidos, contenido fresco todos los días.
Top comments (0)