Módulo 5: Landscape de Vector Databases para AI Engineers
Cápsula 07: Anti-patrones al Elegir Vector DB
Descripción de la cápsula
Hasta ahora has aprendido a comparar proveedores, calcular costos y seguir un framework de decisión. Pero incluso con las mejores herramientas de análisis, los equipos cometen errores predecibles. Estos errores no son técnicos — son cognitivos y organizacionales. Elegir por hype, sobre-ingeniería por escala que no existe, ignorar la complejidad operativa, caer en vendor lock-in sin darse cuenta, o optimizar prematuramente.
En esta cápsula vas a estudiar los 7 anti-patrones más destructivos en la selección de vector databases. Para cada uno verás el patrón, un caso real (anonimizado), las señales de alerta para detectarlo temprano, y la corrección concreta. El objetivo no es que nunca cometas estos errores — es que los reconozcas en los primeros días, no después de 6 meses y $30,000 invertidos.
La diferencia entre un equipo junior y uno senior no es que el senior nunca se equivoca. Es que el senior tiene un vocabulario de errores conocidos y mecanismos para detectarlos antes de que sean costosos.
Anti-patrón 1: "Elegir por hype"
El patrón
Eliges la vector database que más aparece en Twitter, YouTube o HackerNews. La justificación es "todos la usan" o "tiene más GitHub stars".
Caso real
Startup de e-commerce. CTO lee en HackerNews que Pinecone es "la mejor vector DB". Sin evaluar alternativas, compran plan Standard ($200/mes). Su caso: 15K productos con embeddings, 30 queries/día. ChromaDB local hubiera sido gratis y suficiente por 12+ meses.
Costo del anti-patrón: $2,400/año desperdiciados + 2 semanas de integración que pudieron ser 2 horas con ChromaDB.
Señales de alerta
□ La decisión se basa en "X empresa famosa lo usa" sin verificar si tu contexto es similar
□ No puedes nombrar al menos 2 alternativas que evaluaste
□ El argumento principal es "es el más popular" o "tiene más stars"
□ No hay benchmark ni PoC con tu data real
□ La decisión se tomó en menos de 1 día sin análisis formal
La corrección
# Antes de elegir por hype, responde estas 4 preguntas:
evaluation_checklist = {
"1_problem_fit": "¿Este proveedor resuelve MI problema específico, "
"no un problema genérico?",
"2_alternatives": "¿Evalué al menos 2 alternativas con PoC de 1 día?",
"3_data_driven": "¿Mi decisión se basa en benchmarks con MI data, "
"no en benchmarks genéricos?",
"4_context_match": "¿Las empresas que lo usan tienen un contexto similar "
"al mío (escala, equipo, budget)?"
}
# Si alguna respuesta es "no", la decisión es prematura
for key, question in evaluation_checklist.items():
print(f" {question}")
Regla de oro
La popularidad de un proveedor no tiene correlación con su fit para tu caso. Pinecone es excelente para 1M+ vectores con 1000 queries/segundo. Es overkill para 15K vectores con 30 queries/día.
Anti-patrón 2: "Feature checklist sin contexto"
El patrón
Creas una tabla con 20+ features, marcas cuáles tiene cada proveedor, y eliges el que tiene más checkmarks. El problema: tratas todos los features como igualmente importantes.
Caso real
Equipo de ML en empresa financiera. Comparan 5 vector databases con 25 features. Milvus gana con 23/25 checkmarks. Eligen Milvus. Resultado: 3 meses de setup, cluster de Kubernetes complejo, 2 ingenieros dedicados a operación. De los 25 features, solo usan 6. Los 6 que usan los tienen ChromaDB y Qdrant también.
Costo del anti-patrón: $45,000 en ingeniería (3 meses × 2 ingenieros × $7,500/mes) + complejidad operativa permanente.
Señales de alerta
□ Tu tabla de comparación tiene más de 10 features
□ Todos los features tienen el mismo peso (o no tienen peso)
□ No distingues entre "nice to have" y "must have"
□ La opción ganadora es la más compleja/completa
□ No preguntaste "¿cuáles de estos features usaré en los primeros 6 meses?"
La corrección
# En vez de checklist plano, usa pesos
features_weighted = {
# Feature: (peso 1-5, justificación)
"vector_search_basic": (5, "Core. Sin esto no funciona nada"),
"metadata_filtering": (4, "Necesario para filtrar por categoría"),
"hybrid_search": (2, "Nice-to-have, no lo necesitamos hoy"),
"multi_tenancy": (1, "Solo 1 tenant por ahora"),
"gpu_acceleration": (0, "No tenemos GPUs ni las necesitamos"),
"distributed_sharding": (0, "15K vectores, irrelevante"),
"graphql_api": (1, "REST es suficiente"),
"built_in_ml_modules": (1, "Usamos nuestros propios modelos"),
}
# Solo los features con peso >= 3 son decisivos
must_have = {k: v for k, v in features_weighted.items() if v[0] >= 3}
print(f"Features decisivos: {len(must_have)} de {len(features_weighted)}")
# Features decisivos: 2 de 8
# Evalúa SOLO con los features decisivos
# Si ambas opciones cumplen los must-have, desempata por costo/simplicidad
Regla de oro
Elige la opción que tiene los 3-5 features que realmente necesitas HOY, no la que tiene los 25 features que podrías necesitar algún día.
Anti-patrón 3: "Infraestructura primero, producto después"
El patrón
Pasas semanas (o meses) configurando la "arquitectura perfecta" antes de validar que los usuarios quieren lo que estás construyendo. Cluster de Kubernetes, replicación multi-región, CI/CD completo, monitoring avanzado... para un producto que aún no tiene usuarios.
Caso real
Startup de legal-tech. Antes de tener un solo usuario, implementan: Milvus con 3 nodos en Kubernetes, Prometheus + Grafana para monitoring, pipeline de CI/CD con 12 stages, replicación cross-region US-EU. Total: 2 meses de setup. Resultado: 0 usuarios después de 4 meses. La empresa cierra sin validar product-market fit. La infraestructura era perfecta; el producto nunca se usó.
Costo del anti-patrón: 2 meses de runway ($60,000) gastados en infraestructura para un producto que nunca encontró usuarios.
Señales de alerta
□ Llevas > 1 semana en setup de infraestructura sin tener usuarios
□ Tu arquitectura soporta 1M usuarios pero tienes 0
□ Tienes más dashboards de monitoring que features de producto
□ El equipo discute sharding strategies antes de tener 10K vectores
□ Tu pipeline de deploy es más complejo que tu aplicación
La corrección
Principio: "Haz cosas que no escalan" (Paul Graham)
Semana 1-2: ChromaDB local + API mínima → Demo a 5 usuarios
Mes 1: Si hay tracción → Pinecone Free / Qdrant Cloud Free
Mes 3: Si hay pago → Tier pagado del proveedor managed
Mes 6+: Si hay escala real → Evaluar self-hosted o enterprise
# Regla del "Right-Size Infrastructure"
def infrastructure_decision(users: int, vectors: int, revenue: float):
if users == 0:
return "ChromaDB local. Invierte en producto, no en infra."
elif users < 100:
return "Free tier managed. Máximo 1 día de setup."
elif users < 1000:
return "Standard tier managed. Máximo 1 semana de setup."
elif users < 10000:
return "Ahora sí, evalúa arquitectura seria."
else:
return "Enterprise tier o self-hosted con equipo dedicado."
Regla de oro
La mejor infraestructura es la que te permite validar tu hipótesis de negocio lo más rápido posible. Si pasas más tiempo en infra que en producto, tienes las prioridades invertidas.
Anti-patrón 4: "Sobre-ingeniería para escala que no existe"
El patrón
Similar al anterior pero más sutil. No es que construyas infra antes de tener usuarios — es que dimensionas para 10M vectores cuando tienes 50K. O implementas sharding cuando un solo nodo maneja tu carga 20x.
Caso real
SaaS de soporte al cliente. 80K tickets como knowledge base. Implementan Qdrant con 3 nodos replicados, balanceador de carga, auto-scaling basado en CPU. Un solo nodo con 2GB de RAM maneja 80K vectores con 5ms de latencia y 100 QPS. Los 3 nodos + infraestructura cuestan $300/mes en vez de $24/mes.
Costo del anti-patrón: $276/mes extra × 12 meses = $3,312/año + complejidad operativa innecesaria.
Señales de alerta
□ Tu infraestructura usa < 10% de su capacidad
□ Tienes replicación pero un solo nodo maneja tu carga con margen 10x
□ Implementaste auto-scaling pero nunca ha escalado
□ Tu latencia es 5ms pero tu requisito es < 200ms
□ Dimensionaste para "lo que podría pasar" en vez de "lo que está pasando + 3x buffer"
La corrección
Principio: Current load × 3-5x buffer, no current load × 100x
# Fórmula de dimensionamiento correcto
def right_size(current_vectors: int, current_qps: float,
growth_rate: float, months_ahead: int = 6):
projected_vectors = current_vectors * ((1 + growth_rate) ** months_ahead)
buffer_multiplier = 3 # 3x buffer es suficiente
target_capacity = projected_vectors * buffer_multiplier
print(f"Vectores actuales: {current_vectors:,}")
print(f"Proyección {months_ahead} meses ({growth_rate*100:.0f}%/mes): "
f"{projected_vectors:,.0f}")
print(f"Capacidad objetivo (3x buffer): {target_capacity:,.0f}")
if target_capacity < 200_000:
print("→ 1 nodo básico (2-4GB RAM)")
elif target_capacity < 1_000_000:
print("→ 1 nodo medio (8-16GB RAM)")
elif target_capacity < 5_000_000:
print("→ 1 nodo grande (32GB RAM) o 2 nodos medios")
else:
print("→ Cluster (3+ nodos)")
right_size(80_000, 10, 0.15, 6)
# Vectores actuales: 80,000
# Proyección 6 meses (15%/mes): 184,932
# Capacidad objetivo (3x buffer): 554,797
# → 1 nodo básico (2-4GB RAM)
Regla de oro
Dimensiona para 6 meses adelante con 3x buffer, no para 3 años adelante con 10x buffer. Si necesitas más, la migración es una opción; la sobre-ingeniería es un desperdicio.
Anti-patrón 5: "No preparar la salida (vendor lock-in)"
El patrón
Eliges un proveedor y acoplas todo tu código directamente a su SDK. Cuando necesitas migrar (pricing, performance, compliance), descubres que la migración cuesta $10,000-30,000.
Caso real
Startup de fintech. Usan Pinecone por 18 meses. Su código tiene llamadas directas al SDK de Pinecone en 47 archivos. Cuando Pinecone sube precios 40%, quieren migrar a Qdrant. Estimación de migración: 3 semanas de ingeniería ($15,000) + 1 semana de testing ($5,000) + riesgo de bugs en producción.
Costo del anti-patrón: $20,000 de migración + 4 semanas de velocidad de producto perdida + riesgo operativo.
Señales de alerta
□ Tu código importa el SDK del proveedor en > 5 archivos
□ No tienes una interfaz/abstracción entre tu lógica y el proveedor
□ Usas features propietarios que no existen en otros proveedores
□ No tienes un export/backup de tus vectores en formato portable
□ Nunca estimaste cuánto costaría cambiar de proveedor
La corrección
Nivel 1: Capa de abstracción básica (2-4 horas)
from abc import ABC, abstractmethod
from typing import List, Dict, Any, Optional
class VectorStore(ABC):
"""Interfaz que desacopla tu código del proveedor específico."""
@abstractmethod
def upsert(self, ids: List[str], embeddings: List[List[float]],
metadata: List[Dict[str, Any]]) -> None:
pass
@abstractmethod
def query(self, embedding: List[float], top_k: int = 10,
filters: Optional[Dict[str, Any]] = None) -> List[Dict]:
pass
@abstractmethod
def delete(self, ids: List[str]) -> None:
pass
# Implementa ChromaStore(VectorStore), QdrantStore(VectorStore), etc.
# Tu aplicación usa VectorStore, nunca el SDK directamente
# Migrar = cambiar 1 línea de configuración:
# store = ChromaStore("my_collection") # Antes
# store = QdrantStore("https://...", "my_col") # Después
Nivel 2: Backup portátil de vectores (1-2 horas)
Implementa funciones export_vectors() e import_vectors() que serializan a JSON portable. Esto te permite migrar entre proveedores sin re-generar embeddings.
Regla de oro
Siempre ten una capa de abstracción Y un backup portable. El costo de implementarlos (4-6 horas) es 100x menor que el costo de migrar sin ellos ($10,000-30,000).
Anti-patrón 6: "Cambiar de DB por moda"
El patrón
Migras de proveedor porque salió uno nuevo que "es mejor", sin tener un problema concreto con tu proveedor actual. No hay hipótesis, no hay métricas de éxito, solo FOMO.
Caso real
Equipo de 5 devs en edtech. Usan ChromaDB self-hosted sin problemas: 200K vectores, 50ms latencia, $24/mes. Sale Weaviate 2.0 con features de hybrid search y modules. El lead engineer propone migrar "porque es el futuro". Migración: 2 semanas de trabajo, $8,000 en ingeniería. Post-migración: 200K vectores, 40ms latencia, $80/mes. Nunca usaron hybrid search ni modules.
Costo del anti-patrón: $8,000 de migración + $56/mes extra × 12 = $8,672 total para ganar 10ms de latencia que nadie pedía.
Señales de alerta
□ No puedes articular un problema específico con tu proveedor actual
□ La motivación es "X es más moderno/mejor/tiene más hype"
□ No tienes métricas que demuestren que tu proveedor actual es insuficiente
□ No definiste criterios de éxito para la migración ANTES de empezar
□ El trigger de migración fue un blog post, no un incidente o métrica
La corrección
Antes de migrar, completa este template:
## Propuesta de migración
### Problema actual (con datos)
- Latencia actual p95: ___ms (límite aceptable: ___ms)
- Costo actual TCO: $___/mes (límite aceptable: $___/mes)
- Incidentes últimos 3 meses: ___ (límite aceptable: ___)
- Feature faltante que bloquea: ________________
### Hipótesis
"Migrar a [nuevo proveedor] resolverá [problema específico]
reduciendo [métrica] de [valor actual] a [valor objetivo]."
### Criterios de éxito (medibles)
1. Latencia p95 < ___ms (actualmente ___ms)
2. TCO < $___/mes (actualmente $___/mes)
3. Incidentes < ___/trimestre (actualmente ___)
### Costo estimado de migración
- Horas de ingeniería: ___ × $___/hr = $___
- Dual-running: ___ meses × $___/mes = $___
- Riesgo de downtime: ___h × $___/hr = $___
- Total: $___
### ROI
- Ahorro/mejora mensual post-migración: $___
- Payback period: ___ meses
- Si payback > 12 meses → NO migrar
Si no puedes llenar este template con datos reales, no migres.
Regla de oro
Migra por datos, no por hype. Si tu proveedor actual cumple tus requisitos, "mejor" es irrelevante. La migración más barata es la que no haces.
Anti-patrón 7: "Optimización prematura del índice"
El patrón
Pasas días tuneando parámetros de HNSW (ef_construction, M, ef_search), probando diferentes distance metrics, o implementando quantization... cuando tienes 20K vectores y 10 queries por minuto.
Caso real
Data scientist en healthtech. Pasa 1 semana probando 15 combinaciones de parámetros HNSW en ChromaDB con 30K vectores. Encuentra que ef_construction=200, M=32 da 3ms en vez de 5ms con la configuración default. Los usuarios del chatbot nunca notaron diferencia porque la latencia total del request (embedding + search + LLM) es 2,500ms.
Costo del anti-patrón: 1 semana de ingeniería ($4,000) para optimizar 2ms en un pipeline de 2,500ms (mejora de 0.08%).
Señales de alerta
□ Estás optimizando un componente que no es el bottleneck
□ La mejora medida es < 10% del tiempo total del request
□ Tienes < 100K vectores y estás tuneando parámetros de índice
□ No perfilaste el pipeline completo antes de optimizar
□ Tu QPS actual es < 10% de la capacidad default
La corrección
# ANTES de optimizar, perfila el pipeline completo
import time
def profiled_rag_pipeline(query: str):
timings = {}
t0 = time.time()
embedding = generate_embedding(query)
timings["embedding"] = time.time() - t0
t0 = time.time()
results = vector_store.query(embedding, top_k=5)
timings["vector_search"] = time.time() - t0
t0 = time.time()
context = format_context(results)
timings["formatting"] = time.time() - t0
t0 = time.time()
response = llm_generate(query, context)
timings["llm_generation"] = time.time() - t0
total = sum(timings.values())
print("\n--- Pipeline Profiling ---")
for step, duration in timings.items():
pct = (duration / total) * 100
bar = "█" * int(pct / 2)
print(f"{step:20s}: {duration*1000:7.1f}ms ({pct:5.1f}%) {bar}")
print(f"{'TOTAL':20s}: {total*1000:7.1f}ms")
return response
# Resultado típico:
# embedding : 150.0ms ( 5.7%) ███
# vector_search : 15.0ms ( 0.6%)
# formatting : 2.0ms ( 0.1%)
# llm_generation : 2450.0ms (93.6%) ███████████████████████████████████████████████
# TOTAL : 2617.0ms
# → Optimizar vector_search de 15ms a 5ms = 0.4% de mejora total
# → Optimizar llm_generation (streaming, modelo más rápido) = 93.6% del pipeline
Regla de oro
Optimiza el bottleneck, no el componente que conoces mejor. En un pipeline RAG típico, el LLM es 90%+ del tiempo. Vector search es < 5%. Optimizar vector search antes de optimizar el LLM es como pulir el volante de un auto sin motor.
La señal de alerta universal
Si no puedes responder estas 4 preguntas sobre tu decisión, la decisión aún está inmadura:
maturity_check = {
"1_hypothesis": "¿Qué hipótesis valida esta elección? "
"(ej: 'Qdrant Cloud reduce TCO 40% vs self-hosted')",
"2_risk": "¿Qué riesgo principal reduce esta elección? "
"(ej: 'Elimina riesgo de downtime por falta de DevOps')",
"3_metric": "¿Qué métrica confirmará que acertaste? "
"(ej: 'Latencia p95 < 50ms Y TCO < $300/mes en mes 3')",
"4_trigger": "¿Cuál es el trigger de reevaluación? "
"(ej: 'Reevaluar cuando vectores > 500K O TCO > $500/mes')"
}
decision_mature = True
for key, question in maturity_check.items():
answer = input(f"\n{question}\nTu respuesta: ")
if not answer.strip():
print("⚠️ Sin respuesta → decisión inmadura")
decision_mature = False
if not decision_mature:
print("\n→ Vuelve a la matriz de decisión (Cápsula 06)")
Tabla resumen de anti-patrones
| # | Anti-patrón | Costo típico | Detección | Prevención |
|---|---|---|---|---|
| 1 | Elegir por hype | $2K-10K desperdiciados | "No evalué alternativas" | Evaluar ≥ 2 opciones con PoC |
| 2 | Feature checklist sin pesos | $15K-45K en sobre-ingeniería | "Gana la más completa" | Ponderar features, solo top 3-5 |
| 3 | Infra primero, producto después | $30K-60K en runway | "> 1 semana en infra sin usuarios" | Validar con users antes de infra |
| 4 | Sobre-ingeniería de escala | $3K-12K/año desperdiciados | "Infra a < 10% capacidad" | Dimensionar para 6 meses × 3x |
| 5 | No preparar salida | $10K-30K de migración | "SDK directo en > 5 archivos" | Capa de abstracción + backup |
| 6 | Cambiar por moda | $5K-15K por migración | "No hay problema con el actual" | Template de migración con datos |
| 7 | Optimización prematura | $2K-8K en tiempo perdido | "Optimizo < 5% del pipeline" | Perfilar pipeline completo |
Troubleshooting de debate técnico
1. "El equipo no llega a consenso"
Síntoma: 3 ingenieros, 3 opiniones diferentes, reuniones que no avanzan.
Diagnóstico: Están comparando conclusiones sin acordar criterios primero.
Solución paso a paso:
- Acuerden los criterios antes de comparar proveedores (5 variables de la Cápsula 06)
- Asignen pesos a cada criterio por votación (cada quien distribuye 10 puntos)
- Evalúen cada proveedor contra los criterios ponderados
- El puntaje más alto gana — no la voz más fuerte
# Ejemplo de weighted voting
criteria_weights = {
"latency": {"alice": 3, "bob": 2, "carol": 4}, # Total: 9
"cost": {"alice": 3, "bob": 4, "carol": 2}, # Total: 9
"ops": {"alice": 2, "bob": 3, "carol": 2}, # Total: 7
"scale": {"alice": 1, "bob": 1, "carol": 1}, # Total: 3
"lock_in": {"alice": 1, "bob": 0, "carol": 1}, # Total: 2
}
# Consenso: latency y cost pesan más que scale y lock-in
# Ahora evalúen proveedores con estos pesos
2. "Stakeholders piden una marca específica"
Síntoma: El VP de Engineering dice "usemos Pinecone" sin análisis técnico.
Solución:
- Agradece la sugerencia (no la descartes)
- Incluye Pinecone como candidato en tu análisis
- Presenta el análisis completo (TCO, features ponderados, fit por variable)
- Si Pinecone no gana, muestra los datos — no la opinión
- Deja que los datos hablen: "Pinecone es excelente para X. Nuestro caso es Y. Para Y, [alternativa] tiene mejor fit porque [dato concreto]."
3. "Tenemos urgencia y análisis incompleto"
Síntoma: Necesitas decidir hoy, no tienes tiempo para PoC de cada opción.
Solución:
- Toma una decisión temporal explícita — no una "decisión permanente rápida"
- Documenta que es temporal: "Elegimos X por urgencia. Revisión obligatoria en [fecha]."
- Elige la opción más reversible (managed + capa de abstracción)
- Agenda la revisión real para dentro de 30-60 días
## Decisión temporal (ADR-temp-001)
**Fecha:** [hoy]
**Decisión:** Usar Pinecone Free por urgencia de delivery
**Razón:** No hay tiempo para PoC completo. Pinecone Free
es reversible y no tiene costo.
**Revisión obligatoria:** [hoy + 45 días]
**Criterios de revisión:** Evaluar Qdrant Cloud y Weaviate Cloud
con PoC de 1 día cada uno.
4. "Ya elegimos mal y es doloroso admitirlo"
Síntoma: Llevas 6 meses con un proveedor que no es ideal. El equipo no quiere admitir el error porque "ya invertimos mucho".
Diagnóstico: Sunk cost fallacy. El dinero y tiempo ya gastados son irrecuperables. La pregunta correcta no es "¿cuánto invertimos?" sino "¿cuánto más vamos a perder si no cambiamos?"
Solución:
- Calcula el costo mensual de mantener el status quo
- Calcula el costo de migración
- Calcula el payback period
- Si payback < 6 meses, migra. Si > 12 meses, quédate.
5. "El proveedor que elegimos fue adquirido/cambió pricing"
Síntoma: Tu proveedor managed sube precios 50% o es adquirido por una empresa que cambia la dirección del producto.
Solución:
- Si tienes capa de abstracción → migra con costo moderado ($2,000-5,000)
- Si NO tienes capa de abstracción → negocia pricing actual por contrato de 12 meses mientras preparas migración
- Para el futuro: siempre ten la capa de abstracción lista (Anti-patrón 5)
Ejercicios prácticos
Ejercicio 1: Auditoría de anti-patrones
Revisa tu decisión actual (o una decisión hipotética) y marca cuáles anti-patrones aplican:
□ Anti-patrón 1: ¿Elegí por popularidad sin evaluar alternativas?
□ Anti-patrón 2: ¿Comparé features sin ponderar su importancia?
□ Anti-patrón 3: ¿Invertí en infra antes de validar con usuarios?
□ Anti-patrón 4: ¿Dimensioné para 100x mi escala actual?
□ Anti-patrón 5: ¿Tengo lock-in sin capa de abstracción?
□ Anti-patrón 6: ¿Consideré migrar sin un problema concreto?
□ Anti-patrón 7: ¿Optimicé un componente que no es el bottleneck?
Si marcaste 2+, revisa tu decisión.
Solución ejemplo
Proyecto de chatbot RAG con ChromaDB self-hosted, 40K vectores:
☑ Anti-patrón 3: Pasé 1 semana configurando Docker + monitoring
antes de tener usuarios → Hubiera bastado pip install chromadb
☑ Anti-patrón 4: Desplegué en instancia de 16GB RAM para 40K vectores
que caben en 0.3GB → Un droplet de $12 era suficiente
□ Anti-patrón 5: OK, tengo capa de abstracción
□ Anti-patrón 7: OK, no optimicé parámetros del índice aún
Acciones correctivas:
- Migrar a instancia más pequeña ($100/mes → $12/mes, ahorro: $88/mes)
- Simplificar monitoring (Prometheus stack → logs simples de la aplicación)
Ejercicio 2: Template de migración con datos
Imagina que quieres migrar de ChromaDB a Qdrant Cloud. Llena el template de migración:
Solución ejemplo
## Propuesta de migración: ChromaDB → Qdrant Cloud
### Problema actual (con datos)
- Latencia p95: 25ms (límite aceptable: 50ms) → ✅ OK
- TCO: $1,065/mes (límite aceptable: $500/mes) → ❌ EXCEDE
- Incidentes últimos 3 meses: 4 (límite aceptable: 1) → ❌ EXCEDE
- Feature faltante: monitoring integrado, SLA
### Hipótesis
"Migrar a Qdrant Cloud reducirá TCO de $1,065 a ~$250/mes
y eliminará incidentes operativos."
### Criterios de éxito
1. TCO < $300/mes (actualmente $1,065)
2. Incidentes < 1/trimestre (actualmente 4)
3. Latencia p95 < 30ms (actualmente 25ms)
### Costo de migración
- Ingeniería: 20h × $80/hr = $1,600
- Dual-running: 1 mes × $250 = $250
- Re-embedding: $0 (mismos embeddings, solo importar)
- Testing: 8h × $80/hr = $640
- Total: $2,490
### ROI
- Ahorro mensual: $1,065 - $250 = $815/mes
- Payback: $2,490 / $815 = 3.1 meses ✅
- Ahorro año 1: ($815 × 12) - $2,490 = $7,290
Payback de 3 meses → migración justificada con datos.
Ejercicio 3: Profiling de pipeline
Perfila un pipeline RAG hipotético y determina dónde optimizar:
| Componente | Tiempo (ms) | % del total |
|---|---|---|
| Embedding generation | 120 | ? |
| Vector search | 15 | ? |
| Context formatting | 5 | ? |
| LLM generation | 2,800 | ? |
| Response formatting | 10 | ? |
| Total | 2,950 | 100% |
¿Dónde deberías enfocar la optimización?
Solución
| Componente | Tiempo (ms) | % del total | Prioridad |
|---|---|---|---|
| Embedding generation | 120 | 4.1% | Media |
| Vector search | 15 | 0.5% | Baja |
| Context formatting | 5 | 0.2% | Nula |
| LLM generation | 2,800 | 94.9% | ALTA |
| Response formatting | 10 | 0.3% | Nula |
Dónde optimizar (en orden):
- LLM generation (94.9%): Usar streaming, modelo más rápido, prompt más corto, o cache de respuestas frecuentes
- Embedding generation (4.1%): Usar modelo local en vez de API, o cachear embeddings de queries frecuentes
- Vector search (0.5%): NO optimizar. Aunque lo hagas 10x más rápido (15ms → 1.5ms), solo ganas 0.46% del total
Optimizar vector search aquí es Anti-patrón 7.
Ejercicio 4: Debate simulado — defiende tu posición
Elige un lado y prepara 3 argumentos con datos:
Posición A: "Siempre empieza con managed, migra a self-hosted solo si es necesario." Posición B: "Siempre empieza con self-hosted open-source, migra a managed solo si es necesario."
Solución
Posición A (Managed first) — 3 argumentos:
-
TCO menor para equipos < 10 personas:
- Managed: $250/mes (servicio + 2h ops)
- Self-hosted: $1,065/mes (infra + 14h ops)
- Ahorro: $815/mes = $9,780/año
-
Time-to-market 3x más rápido:
- Managed: 1-2 semanas para producción
- Self-hosted: 4-6 semanas para producción
- En startup, 4 semanas = $60,000 de runway
-
Riesgo operativo 80% menor:
- Managed: SLA del proveedor, auto-scaling, backups incluidos
- Self-hosted: Tú eres responsable de todo a las 3am
Posición B (Self-hosted first) — 3 argumentos:
-
Zero lock-in desde día 1:
- Open-source: migras cuando quieras sin costo extra
- Managed: migrar cuesta $10,000-30,000
-
Costo infra 5-10x menor a escala:
- Self-hosted 1M vectors: $180/mes (infra directa)
- Managed 1M vectors: $800-1,000/mes
- Ahorro a 2 años: $15,000-20,000
-
Control total para compliance:
- Self-hosted: datos en tu infra, auditable, cualquier regulación
- Managed: dependes de certificaciones del proveedor
Mi recomendación: Posición A para el 80% de los equipos. Posición B solo si tienes DevOps dedicado + requisitos de compliance estrictos.
Conexión con proyecto: Decision Tree
En tu proyecto final de Decision Tree, incluye una sección de validación de anti-patrones:
- Para cada recomendación que tu árbol genere, verifica los 7 anti-patrones
- Incluye warnings automáticos (ej: "si el usuario tiene < 10K vectores y elige Milvus, mostrar warning de Anti-patrón 4")
- Genera un "health check" de la decisión con las 4 preguntas de madurez
Resumen
- Anti-patrón 1 (Hype): La popularidad de un proveedor no implica fit para tu caso. Evalúa ≥ 2 alternativas con PoC.
- Anti-patrón 2 (Feature checklist): No compares 25 features con el mismo peso. Pondera los 3-5 que realmente necesitas.
- Anti-patrón 3 (Infra first): Valida producto con usuarios antes de invertir en infraestructura.
pip install chromadb> cluster de Kubernetes sin usuarios. - Anti-patrón 4 (Sobre-ingeniería): Dimensiona para 6 meses × 3x buffer, no para 3 años × 100x.
- Anti-patrón 5 (No preparar salida): Siempre ten capa de abstracción + backup portable. Cuesta 4-6 horas. Ahorra $10,000-30,000 en migración futura.
- Anti-patrón 6 (Migrar por moda): Migra por datos y métricas, no por blog posts. Si no puedes llenar el template de migración, no migres.
- Anti-patrón 7 (Optimización prematura): Perfila el pipeline completo antes de optimizar. Vector search suele ser < 5% del tiempo total en RAG.
- Señal universal de decisión inmadura: No poder responder "qué hipótesis valida", "qué riesgo reduce", "qué métrica confirma" y "cuál es el trigger de reevaluación".
Recursos adicionales
- Martin Fowler — Microservice Trade-offs — Framework de trade-offs aplicable a cualquier decisión de arquitectura
- Paul Graham — Do Things That Don't Scale — Filosofía de empezar simple
- Architecture Decision Records — Formato estándar para documentar decisiones técnicas
- Sunk Cost Fallacy in Engineering — Por qué es difícil admitir errores técnicos
- ANN Benchmarks — Para evaluar con datos reales, no con hype
- CNCF Technology Radar — Evaluación neutral de tecnologías por la comunidad
- Choosing the Right Vector Database — Perspectiva vendor-neutral actualizada
- Donald Knuth — Premature Optimization — La raíz del Anti-patrón 7
Tiempo estimado: 30-40 minutos
Siguiente: 08-proyecto-decision-tree.md