Módulo 2: Latencia y costo como arquitectura
1. Presentación del módulo: latencia y costo como arquitectura
Descripción
Al terminar esta lección vas a entender la idea que sostiene todo el módulo, y que la mayoría de los equipos aprende tarde y caro: la latencia y el costo de un LLM no son un detalle de infraestructura, son restricciones de primera clase del diseño. En el módulo 1 viste que un LLM no es una función normal porque es probabilístico —no puedes afirmar su salida exacta—. Aquí sumamos las otras dos propiedades que lo separan de una función clásica, y son igual de arquitectónicas: el LLM es lento (tarda cientos de milisegundos o segundos, no microsegundos) y cuesta dinero por llamada (se paga por token, cada vez). Estas dos propiedades cambian cómo diseñas, dónde pones el componente, qué modelo usas para qué, y qué guardas para no volver a pagarlo. Si las ignoras hasta el final, terminas con dos sorpresas: una feature que se siente lenta y una factura mensual que se come el margen.
Esto importa porque la frase más peligrosa al meter IA en un sistema es "es solo otra llamada a una API". Suena inofensiva, y es exactamente la que precede al desastre. Una llamada a una API normal —tu base de datos, otro microservicio— responde en milisegundos de un dígito y cuesta esencialmente cero, así que llamarla mil o un millón de veces no cambia tu arquitectura. Una llamada a un LLM rompe las dos suposiciones a la vez: tarda cientos de veces más y cuesta dinero real que se multiplica por cada llamada. Meterlo en el camino crítico de una búsqueda sin pensar en su latencia, o dejarlo atender todo el tráfico sin pensar en su costo, no es un descuido menor: es un error de diseño que se paga en usuarios que se van y en dinero que se fuga. Y —la buena noticia— se arregla con arquitectura, no con hardware: decidiendo qué modelo atiende qué, qué se cachea, qué se saca del camino crítico, y cuánto puede tardar y costar cada operación antes de considerar el diseño roto.
Conexión con el módulo: esta lección es el mapa, no el territorio. Aquí no diseñas nada todavía; entiendes por qué las seis lecciones que siguen van en el orden que van. Primero las dos físicas nuevas: la lección 2 mide qué significa "lento" y "cuesta por llamada" —la latencia que crece con los tokens, el precio por token, el taxímetro del costo a escala—. Luego la restricción que las convierte en diseño: la lección 3 define el latency budget y el cost budget de una feature, el umbral que la arquitectura debe respetar. Con el presupuesto en la mano, las tres técnicas que lo hacen cumplir: la lección 4, el model cascade (barato primero, caro solo si hace falta); la lección 5, la caché (no volver a pagar lo ya calculado); la lección 6, async y streaming (cuando el usuario no puede esperar el bloque completo). Y la lección 7 los compone en un solo camino de petición y demuestra, ejecutando, que juntos meten la feature dentro de su presupuesto. La lección 8 —el proyecto— te pone a diseñar el presupuesto de una feature de Mercado con tus manos.
Tres analogías: el taxímetro, el call center y la caja rápida
Antes de bajar al código, tres imágenes cotidianas que vas a reconocer en cada lección del módulo. Cada una captura una de las ideas centrales.
El taxímetro. Cuando subes a un taxi, hay un aparato que corre desde que arrancas: cada cuadra que avanzas, el número sube. No pagas una tarifa plana por "usar el taxi"; pagas por cada unidad de recorrido, y al final la suma es lo que marca el aparato. Un LLM funciona igual: cada llamada tiene su taxímetro. No pagas una licencia mensual fija por "tener IA"; pagas por cada token que entra y cada token que sale, en cada llamada. Una llamada suelta cuesta una fracción de centavo y no la sientes —como una cuadra en taxi—. Pero un marketplace hace cientos de miles de búsquedas al día, y ahí el taxímetro se vuelve la factura: la misma llamada barata, multiplicada por el volumen real, son miles de dólares al mes. La lección 2 te pone a ver ese taxímetro corriendo.
El call center junior→senior. Un call center bien montado no pone a su mejor agente —el senior, caro, con años de experiencia— a atender todas las llamadas. Sería un desperdicio: la mayoría de las llamadas son fáciles ("¿cuál es su horario?", "¿cómo reseteo mi contraseña?") y las resuelve un agente junior en segundos, a una fracción del costo. El senior se reserva para lo difícil: el reclamo complejo, el caso que el junior no pudo. La regla es atiende con el barato, escala al caro solo cuando hace falta. Ese es, exacto, el model cascade de la lección 4: un clasificador barato mira la query, manda las fáciles al modelo barato y solo las difíciles al caro. Poner al modelo caro a atender todo "por si acaso" es como poner a tu agente senior a contestar en qué horario abres: funciona, pero pagas de más por cada llamada trivial.
La caja rápida del súper. El supermercado no manda a todos por la misma fila. Tiene una caja rápida para el que lleva pocos artículos, precisamente para no hacerlo esperar detrás del que lleva el carrito lleno. Es una decisión de diseño sobre quién espera cuánto: reconoce que no toda operación merece la misma latencia, y organiza el flujo para que la rápida sea rápida. En IA, esa idea aparece en dos lugares. En la caché (lección 5): la respuesta que ya calculaste no vuelve a la fila, se sirve al instante —como el cliente que ya pagó y solo pasa a recoger—. Y en async/streaming (lección 6): cuando una operación tarda segundos, o le muestras al usuario lo que va saliendo (streaming, para que no mire una fila detenida) o la sacas de la fila principal por completo (async, se procesa aparte y se avisa cuando está lista). El error opuesto —una sola fila lenta para todo— es el síncrono que hace esperar al usuario tres segundos mirando una pantalla en blanco.
Guarda las tres. El taxímetro es por qué importa el costo; el call center es cómo lo bajas sin perder calidad; la caja rápida es cómo organizas la latencia para que el usuario no sufra. El módulo entero es aprender a montar esas tres cosas en una feature real.
El caso: las features de IA de Mercado
Bajemos a Mercado, el marketplace del ecosistema. Mercado añadió features de IA, y dos de ellas nos acompañan todo el módulo porque exhiben las dos restricciones de forma distinta:
- La búsqueda semántica: cuando un cliente escribe "algo para escuchar música corriendo", el sistema no hace un
LIKE '%música%'; usa un LLM para entender la intención y reordenar los productos por relevancia. Es de alto volumen (cada búsqueda del sitio la toca) y vive en el camino crítico: si tarda, el cliente lo siente al instante. Aquí muerden las dos restricciones: la latencia (el usuario espera) y el costo (multiplicado por cada búsqueda). - El agente de soporte: un asistente conversacional que responde dudas de clientes ("¿dónde está mi pedido?", "¿cómo devuelvo esto?"). Es conversacional —varios turnos por conversación, cada turno una llamada al LLM— así que el costo se acumula por turno, y la latencia por turno define si la conversación se siente ágil o pastosa.
A lo largo del módulo le vamos a poner a cada una su presupuesto de latencia y costo, y le vamos a diseñar la arquitectura que lo respeta: qué modelo atiende cada query, qué se cachea, qué se saca del camino crítico. No vamos a construir el LLM ni a entrenar nada —eso es de AI Engineering—; vamos a arquitectar la feature alrededor del LLM para que quepa en su presupuesto.
Y para arrancar, veamos el módulo entero condensado en una tabla ejecutada. Fíjate bien, porque aquí está la tesis en cifras.
# Leccion 01 (intro) — el modulo en miniatura: dos fisicas nuevas + el presupuesto
# Todo SIMULADO. Cero red, cero API, cero claves. Semilla fija.
import random
MODELS = {
"cheap": dict(usd_in=0.0008, usd_out=0.004, base_ms=90, ms_per_tok=0.4),
"strong": dict(usd_in=0.008, usd_out=0.040, base_ms=300, ms_per_tok=3.0),
}
def call_llm(model, in_tokens, out_tokens):
m = MODELS[model]
return m["base_ms"] + out_tokens * m["ms_per_tok"], \
(in_tokens/1000)*m["usd_in"] + (out_tokens/1000)*m["usd_out"]
# El presupuesto de la busqueda semantica de Mercado.
MONTHLY_COST_BUDGET = 3000.0
SEARCHES_PER_DAY = 30_000
# Un workload chico: 1000 busquedas, 30% dificiles, muchas repetidas.
random.seed(1)
N = 1000
POOL = [f"q_{i:02d}" for i in range(60)]
W = [1.0/(i+1) for i in range(60)]
DIFF = {q: (random.random() < 0.30) for q in POOL}
_uid = [0]
def make():
if random.random() < 0.20:
_uid[0] += 1; return (f"novel_{_uid[0]}", True)
q = random.choices(POOL, weights=W, k=1)[0]
return (q, DIFF[q])
qs = [make() for _ in range(N)]
def out_for(h): return 300 if h else 150
def run(smart):
cache, cost = set(), 0.0
for text, hard in qs:
if smart and text in cache: # cache: gratis
continue
if smart: cache.add(text)
model = ("strong" if hard else "cheap") if smart else "strong" # cascade
_, c = call_llm(model, 300, out_for(hard))
cost += c
return cost
def monthly(c): return c * (SEARCHES_PER_DAY * 30 / N)
naive = monthly(run(smart=False)) # todo al modelo caro, sin cache
smart = monthly(run(smart=True)) # cascade + cache
print(f"{'estrategia':<24}{'usd_mes':>12}{'presupuesto':>13}")
print(f"{'todo-al-caro (naive)':<24}{naive:>12,.0f}{('VIOLA' if naive>MONTHLY_COST_BUDGET else 'OK'):>13}")
print(f"{'cascade + cache':<24}{smart:>12,.0f}{('VIOLA' if smart>MONTHLY_COST_BUDGET else 'OK'):>13}")
print(f"\npresupuesto = ${MONTHLY_COST_BUDGET:,.0f}/mes ({SEARCHES_PER_DAY:,} busquedas/dia)")
print(f"la misma feature, {(1-smart/naive)*100:.0f}% menos costo — sin tocar GPUs ni el modelo, solo arquitectura")
Qué esperar. Al correrlo:
estrategia usd_mes presupuesto
todo-al-caro (naive) 10,535 VIOLA
cascade + cache 2,700 OK
presupuesto = $3,000/mes (30,000 busquedas/dia)
la misma feature, 74% menos costo — sin tocar GPUs ni el modelo, solo arquitectura
Detente en esos dos renglones, porque son el módulo entero en miniatura. La misma feature —la misma búsqueda semántica, respondiendo las mismas queries— cuesta $10,535 al mes si la diseñas de la forma ingenua ("todo al modelo caro, sin guardar nada") y $2,700 al mes si la diseñas con dos técnicas de arquitectura: el cascade (fáciles al barato) y la caché (no repagar lo repetido). El presupuesto de la feature es $3,000 al mes. La versión ingenua lo viola por más del triple; la versión con arquitectura lo respeta con holgura. Y —lee la última línea— la diferencia no vino de comprar GPUs más rápidas ni de cambiar el modelo por uno más eficiente. Vino de decisiones de diseño: qué modelo atiende qué, y qué no se vuelve a pagar. Eso es exactamente lo que significa "latencia y costo como arquitectura": el ahorro está en cómo rodeas al modelo, no en el modelo.
No entiendas todavía cómo funciona cada pieza —para eso son las lecciones—. Quédate con la forma del resultado: dos diseños de la misma feature, uno que quiebra el presupuesto y otro que cabe en él, con solo cambiar la arquitectura alrededor del LLM.
El mapa de las seis lecciones
Las seis lecciones que siguen van en este orden porque cada una arma la pieza que la siguiente necesita.
| Lección | Qué te da | Por qué va aquí |
|---|---|---|
| 2 | Las dos físicas medidas: latencia por tokens, costo por token, el taxímetro a escala | No puedes presupuestar lo que no sabes medir; primero cuantificas |
| 3 | El presupuesto (latency + cost budget) como umbral explícito, con la compuerta que lo verifica | El presupuesto es la restricción que todo el resto del módulo tiene que cumplir |
| 4 | El model cascade: clasificar y enrutar, barato primero | La técnica de mayor palanca sobre el costo sin sacrificar calidad donde importa |
| 5 | La caché (exacta y semántica), el hit-rate y su ahorro | La segunda gran palanca: a alto volumen, no repagar es el mayor ahorro |
| 6 | Async y streaming: latencia percibida vs real | Cuando la operación tarda segundos, el diseño del cuándo importa tanto como el cuánto |
| 7 | La síntesis: componer cache + cascade + presupuesto en un camino de petición | Cierra la tesis: las técnicas se acumulan y meten la feature en su presupuesto |
El arco es: primero aprendes a medir las dos restricciones (2), luego a acotarlas con un presupuesto (3), luego las tres técnicas que lo hacen cumplir —enrutar (4), no repagar (5), no bloquear (6)— y al final las compones en un solo diseño (7). La lección 8 —el proyecto— junta todo sobre una feature de Mercado que diseñas de cero, para que confirmes que aprendiste el método y no memorizaste una tabla.
Lo que este módulo NO toca
Conviene marcar la frontera desde ahora, porque hay un tema vecino que parece de aquí y es de otra parte del ecosistema.
La optimización de inferencia es de AI Engineering / infraestructura, no de aquí. Este módulo baja el costo y la latencia con arquitectura: qué modelo usas, qué cacheas, qué sacas del camino crítico. Hay otra familia entera de técnicas para hacer que el mismo modelo corra más rápido y más barato en el hardware —cuantización (usar menos bits por peso), batching de peticiones en la GPU, destilación, servir el modelo con un runtime optimizado, elegir el tamaño de GPU—. Todo eso es real y valioso, pero es infraestructura de modelos, no arquitectura de sistemas, y se enseña en los ecosistemas de AI Engineering e infra. La regla mental: si la técnica cambia cómo corre el modelo por dentro, no es de este módulo; si cambia cómo lo rodea tu sistema (cuándo lo llamas, con qué modelo, qué guardas), sí lo es. En todo el módulo el modelo es una caja negra que tarda y cuesta lo que tarda y cuesta; nuestro trabajo es el diseño alrededor de esa caja.
La calidad del modelo —si su respuesta es buena— es el módulo 3. Cuando en la lección 4 mandemos una query fácil al modelo barato, surgirá la pregunta obvia: "¿y si el barato responde peor?". Esa es una pregunta de calidad, y se responde con un eval —la compuerta que mide si una respuesta es lo bastante buena—, que es todo el módulo 3. Aquí asumimos que el enrutamiento es correcto y medimos el ahorro; verificar que la calidad no se cae al abaratar es el siguiente módulo. Los dos van de la mano: el cost budget (este módulo) y el quality gate (el siguiente) son las dos compuertas que toda feature de IA necesita.
El capacity planning a fondo es de system-design. Vamos a usar números —latencia, costo, volumen— para acotar un presupuesto. Pero el cálculo serio de cuántas peticiones por segundo aguanta el sistema, cómo se escala horizontalmente, cómo se dimensiona a cinco años, es de system-design-fundamentals y system-design-scaling. Aquí los números existen para fijar y verificar un presupuesto de feature, no para dimensionar la infraestructura de Mercado.
Errores comunes
Tratar el LLM como "solo otra llamada a una API" (de modelo mental). Qué pasa: el equipo mete el LLM en el camino crítico como si fuera un microservicio interno más, sin presupuestar su latencia ni su costo. Semanas después, dos sorpresas: la feature se siente lenta (segundos donde el usuario esperaba milisegundos) y la factura mensual es diez veces lo estimado. Por qué pasa: la palabra "API" evoca algo barato y rápido, y el LLM lo parece cuando lo pruebas una vez con una query. Cómo detectarlo: si en el diseño de una feature de IA no hay un número de latencia esperada ni una proyección de costo mensual a volumen real, no la presupuestaste. Cómo corregirlo: es el módulo entero —medir (lección 2), presupuestar (lección 3), y diseñar dentro del presupuesto (lecciones 4–7)—.
Mandar todo al modelo más caro "por si acaso" (de sobre-ingeniería del costo). Qué pasa: para asegurar la mejor calidad, el equipo enruta todas las queries al modelo más potente. Funciona, pero paga el precio premium por cada query trivial —la mayoría—, y el costo se dispara sin que la calidad extra sirva de nada en las queries fáciles. Por qué pasa: se confunde "el modelo caro es mejor" con "el modelo caro es mejor para todo", y se olvida que la mayoría del tráfico no necesita esa potencia. Cómo detectarlo: si un solo modelo atiende el 100% del tráfico y es el más caro, estás pagando de más. Cómo corregirlo: el model cascade de la lección 4 —clasificar y enrutar, como el call center—.
Ignorar el costo hasta que llega la factura (de miopía financiera). Qué pasa: nadie mira el costo durante el diseño porque "una llamada cuesta centavos"; el costo solo se vuelve visible cuando llega el cargo del proveedor a fin de mes, y para entonces la arquitectura ya está montada y es cara de cambiar. Por qué pasa: el costo por llamada es invisible y minúsculo; el costo agregado es enorme pero solo aparece tarde, sumado. Cómo detectarlo: si no puedes decir hoy cuánto costará tu feature de IA al mes al volumen esperado, el costo te va a sorprender. Cómo corregirlo: pon el taxímetro a correr en el diseño —proyecta el costo mensual a volumen real desde el día uno (lección 2)— y ponle un presupuesto explícito (lección 3).
Ejercicios
Ejercicio 1 — Traduce la analogía al diseño. Para cada analogía del módulo, di qué técnica arquitectónica representa y da un ejemplo concreto en una feature de Mercado. (a) El taxímetro que corre en cada cuadra. (b) El call center que atiende con el junior y escala al senior. (c) La caja rápida del súper para pocos artículos.
Ver solución
- (a) El taxímetro → el costo por llamada que escala con el volumen. Representa la restricción de costo, no una técnica de ahorro: cada llamada al LLM cuesta, y el total es esa suma. Ejemplo en Mercado: cada búsqueda semántica es una "cuadra" con su costo; a 30,000 búsquedas al día, el taxímetro marca miles de dólares al mes. Reconocerlo es el primer paso para presupuestarlo.
- (b) El call center junior→senior → el model cascade. Clasificar la dificultad y enrutar: fácil al modelo barato, difícil al caro. Ejemplo en Mercado: la búsqueda "iphone" es trivial y la atiende el modelo barato; "algo elegante pero informal para una boda en la playa" necesita el modelo fuerte. Solo lo difícil paga el precio premium.
- (c) La caja rápida → la caché (y, en su versión de no-bloquear, async/streaming). No hacer esperar lo que puede ir por una vía más rápida. Ejemplo en Mercado: la búsqueda "laptop", que ya se hizo mil veces hoy, se sirve del caché al instante (caja rápida) en vez de recalcularla; y la generación larga de "describe tu producto" se saca del camino crítico (async) para no detener la fila.
Lo importante: cada analogía es una idea distinta —el taxímetro es por qué importa, el call center y la caja rápida son cómo lo resuelves—.
Ejercicio 2 — La frase peligrosa. Un compañero propone la búsqueda semántica así: "Es fácil, es solo otra llamada a una API: le mandas la query al modelo más potente y te devuelve los productos ordenados. Lo conectamos al buscador y listo." Identifica las dos suposiciones ocultas que este plan hace sobre latencia y costo, y por qué cada una es un problema.
Ver solución
Las dos suposiciones ocultas, una por cada física nueva del módulo:
- Suposición de latencia: "responde rápido como cualquier API". Un LLM potente tarda cientos de milisegundos a segundos, no los pocos milisegundos de un servicio interno. Puesto en el camino crítico de cada búsqueda —y "conectarlo al buscador y listo" lo pone justo ahí, síncrono— hace que el buscador se sienta lento. El problema: la latencia del modelo se convierte en la latencia percibida del producto, y el usuario abandona.
- Suposición de costo: "cuesta poco, es solo una llamada". Cada llamada al modelo más potente cuesta el precio premium por token, y "el buscador" son decenas de miles de búsquedas al día. El problema: "solo una llamada" multiplicado por el volumen real es una factura de miles de dólares al mes, que nadie presupuestó porque el costo por llamada parecía insignificante.
El plan no está mal como punto de partida —el modelo potente da buena calidad—; está incompleto: le falta el presupuesto y le falta la arquitectura que lo respete (cascade, caché, streaming). Es exactamente el diseño "naive" de $10,535/mes de la tabla del inicio.
Ejercicio 3 — ¿Arquitectura o infraestructura? Para cada técnica, di si es del alcance de este módulo (arquitectura: cómo rodeas al modelo) o de la frontera de AI Engineering/infra (optimización de inferencia: cómo corre el modelo por dentro), y por qué. (a) Cachear las respuestas de las búsquedas repetidas. (b) Cuantizar el modelo a 4 bits para que ocupe menos memoria en la GPU. (c) Mandar las queries fáciles a un modelo más pequeño. (d) Hacer batching de varias peticiones en una sola pasada de la GPU.
Ver solución
- (a) Cachear respuestas → arquitectura (este módulo). No cambia cómo corre el modelo; cambia cuándo lo llamas (no lo llamas si ya tienes la respuesta). Es diseño alrededor del modelo. Lección 5.
- (b) Cuantizar a 4 bits → infraestructura (frontera, AI Eng/infra). Cambia cómo está representado el modelo por dentro para que corra más rápido/barato en el hardware. No es una decisión de arquitectura de sistemas; es optimización de inferencia. Fuera de este módulo.
- (c) Enrutar las fáciles a un modelo pequeño → arquitectura (este módulo). No cambia cómo corre ningún modelo; decide qué modelo atiende qué query. Es el model cascade. Lección 4.
- (d) Batching en la GPU → infraestructura (frontera). Agrupar peticiones para aprovechar mejor el hardware es una técnica de serving del modelo, interna a cómo se ejecuta la inferencia. Fuera de este módulo.
La regla que separa: si la técnica cambia cómo corre el modelo por dentro (b, d), es infraestructura; si cambia cómo lo rodea tu sistema —cuándo lo llamas, con cuál, qué guardas— (a, c), es arquitectura, y es de aquí.
Resumen y siguiente paso
En esta lección conociste la tesis del módulo: la latencia y el costo del LLM son restricciones de primera clase del diseño, no un detalle de infraestructura. Viste las dos físicas nuevas que separan al LLM de una función clásica —es lento (cientos de ms a segundos) y cuesta por llamada (por token, cada vez)— y por qué "es solo otra llamada a una API" es la frase que precede a la factura sorpresa y a la pantalla de carga. Las tres analogías te dieron el marco: el taxímetro (por qué el costo importa, escala con las llamadas), el call center junior→senior (cómo bajarlo con el cascade sin perder calidad) y la caja rápida (cómo organizar la latencia con caché y async). Y en la tabla ejecutada viste la tesis en cifras: la misma búsqueda semántica de Mercado cuesta $10,535/mes en su versión ingenua y $2,700/mes con cascade + caché —un 74% menos, solo con arquitectura, sin tocar el modelo ni el hardware—.
Antes de avanzar deberías poder: explicar por qué un LLM rompe las dos suposiciones de una función normal (costo ~0 y latencia ~0); reconocer la frase "es solo otra llamada a una API" como un diseño incompleto al que le falta presupuesto y arquitectura; y separar una técnica de arquitectura (cómo rodeas al modelo) de una de infraestructura (cómo corre el modelo), que está fuera de este módulo.
Lo que sigue es medir con precisión las dos restricciones, porque no puedes presupuestar lo que no sabes cuantificar. En la lección 2 vas a poner un número a "lento" —la latencia que crece con los tokens de salida— y a "cuesta por llamada" —el precio por token, y por qué el modelo caro cuesta cerca de diez veces el barato—, y vas a ver el taxímetro corriendo: cómo la misma llamada barata se convierte en $252, $2,520 o $25,200 al mes según el volumen. Es el paso de "sé que el LLM es lento y caro" a "sé exactamente cuánto, y puedo proyectarlo a la escala de Mercado".
Recursos
- Anthropic — Models overview (docs de Claude) — el panorama de modelos por familia (de más rápido/barato a más lento/capaz); la base conceptual de por qué existe un "cheap model" y un "strong model" que este módulo enruta, sin fijar versión.
- martinfowler.com — "Emerging Patterns in Building GenAI Applications", Bharani Subramaniam y Martin Fowler — el catálogo de patrones de arquitectura para apps con LLM (incluye el enfoque de tratar el costo y la latencia como restricciones de diseño); la referencia ensayística que enmarca todo el módulo.
- Chip Huyen — AI Engineering (O'Reilly), capítulos de cost y latency — el tratamiento sistemático de cómo el costo y la latencia moldean el diseño de un sistema de IA, incluido el trade-off de modelos por tamaño; el libro de cabecera para la parte de presupuestos y cascade.