Disaggregated serving: prefill y decode en pods especializados

TL;DR

La inferencia LLM tiene dos fases con perfiles opuestos: prefill (procesar el prompt entero de golpe) es compute-bound, decode (generar token a token) es memory-bandwidth-bound. Ejecutarlas en la misma GPU obliga a elegir entre dos hardware óptimos incompatibles, y deja entre el 60 % y el 80 % de la capacidad de pico sin usar. La industria ha consolidado el patrón en 2026: disaggregated serving — pods separados para cada fase, conectados por un canal de transferencia de KV cache (NIXL sobre UCX, RDMA, o NCCL en su defecto). DistServe demostró 7,4× más request rate a igual SLO; NVIDIA Dynamo 1.0 (GA en GTC 2026) lleva el patrón a producción a escala datacenter. Mezclar hardware heterogéneo —H100 para prefill, GPUs commodity para decode— recorta hasta el 48 % del coste por token. Este artículo explica el porqué, el cómo, y los números que importan para una infraestructura on-premise típica.

La analogía: la cocina con dos brigadas

Una cocina industrial seria —cualquiera que sirva más de 50 cubiertos por noche— funciona con dos brigadas distintas y dos espacios físicos separados.

La brigada de prep empieza al alba. Su trabajo es la mise en place: cortar, marinar, blanquear, hervir fondos, preparar componentes complejos. Equipamiento: cuchillos buenos, fogones grandes, hornos de convección, ollas de 40 litros. Es trabajo intensivo en capacidad y se hace de golpe. Cuando termina, queda todo en bandejas etiquetadas listas para usar.

La brigada de pase entra a media tarde. Su trabajo es el servicio: tomar las bandejas de la prep, calentar porciones, emplatar, montar el pase. Equipamiento: salamandras, planchas pequeñas, espátulas finas, mucha vajilla. Es trabajo de muñeca, de ritmo, de no fallar al cliente que tiene el plato delante. La capacidad por hora importa menos que la latencia por plato.

Si haces que la misma persona haga prep y pase, las dos cosas sufren. El cocinero está parado mientras hace mise en place a media tarde. Tiene que parar a emplatar cuando entran cinco pedidos a la vez. Su equipo de trabajo está diseñado para uno o para el otro, no para ambos.

Las cocinas serias resolvieron esto hace décadas: brigadas separadas, espacios separados, equipo separado. Lo único que cruza entre ambas son las bandejas de mise en place.

Las bandejas son el KV cache. La separación es disaggregated serving. El pase de la prep al servicio es la transferencia de KV cache, hoy resuelta con NIXL sobre RDMA. Y los pods especializados son las dos brigadas con sus equipos óptimos.

Recap rápido: prefill y decode

Una petición a un LLM atraviesa siempre dos fases:

Prefill. Coger el prompt completo (por ejemplo, 4.000 tokens) y procesarlo de una sola pasada por todas las capas del modelo. El resultado es el KV cache de esos 4.000 tokens (ver el artículo previo sobre KV cache si quieres recordar qué guarda exactamente). Este paso es masivamente paralelo: todos los tokens van a la vez por las matrices de atención, lo que se traduce en multiplicaciones de matrices enormes y densas. La GPU está al 90-95 % de uso de compute. TTFT (time to first token) lo determina esta fase.

Decode. Una vez está el KV cache listo, el modelo genera tokens uno por uno. Cada token nuevo es una pasada por todas las capas con un solo vector de query, leyendo todo el KV cache acumulado para calcular la atención. No hay paralelismo entre tokens (cada uno depende del anterior). Lo que limita aquí no es el compute sino el ancho de banda: cada paso hay que leer los pesos completos del modelo desde HBM. La GPU está al 20-40 % de uso de compute, pero al 90 % de uso del HBM. TBT (time between tokens) lo determina esta fase.

FaseCaracterísticaCuello de botellaMétrica clave
PrefillCómputo masivo paralelo sobre N tokens de golpeTFLOPS (compute)TTFT
DecodeStreaming de pesos desde HBM, 1 token cada vezBandwidth HBMTBT (inter-token latency)
Utilización de la GPU durante cada fase (orden de magnitud típico)100%75%50%25%0%PREFILLcompute-boundDECODEmemory-bound95%compute60%HBM35%compute90%HBM

La asimetría es estructural: prefill quema el compute y deja la memoria a media, decode hace lo contrario. Una GPU diseñada para ser excelente en ambos a la vez es una GPU diseñada para estar mal aprovechada todo el tiempo.

Por qué juntarlas en la misma GPU es un mal negocio

Hasta 2023, la asunción universal era ejecutar prefill y decode en el mismo proceso de inferencia, sobre la misma GPU. El motor scheduler (vLLM, TGI, Triton) decidía en cada ciclo si hacer prefill de una petición nueva o decode de las que ya estaban en marcha. La intuición era que compartir hardware ahorra coste.

La intuición es incorrecta. El problema tiene tres caras:

Interferencia en latencia. Cuando el motor decide hacer prefill de una petición nueva, interrumpe todos los decodes en curso. Eso sube el TBT de las otras peticiones. El usuario que estaba viendo tokens caer fluidos en su pantalla nota un parón de varios cientos de milisegundos. Esto se conoce como prefill-decode interference y degrada la experiencia de forma visible a medida que sube la concurrencia.

Hardware sub-óptimo para cada fase. Una H100 SXM tiene 989 TFLOPS BF16 de compute y 3,35 TB/s de HBM3. Es excelente para prefill, donde el compute es el límite. Para decode, donde lo único que importa es el bandwidth, esos 989 TFLOPS están desaprovechados al 60-70 %. Inversamente, una GPU con menos compute pero similar bandwidth relativo (RTX 4090, L40S) resolvería el decode igual de bien por una fracción del precio.

Utilización agregada baja. En workloads reales con Llama 3 70B y outputs de 512 tokens, alrededor del 80 % del wall-clock se gasta en decode. Eso quiere decir que el 80 % del presupuesto de tu cluster H100 está haciendo lecturas de memoria, no cálculos. Es como pagar un Ferrari para usarlo en cola de aparcamiento.

La idea: pods especializados, KV cache como entregable

Disaggregated serving rompe el ciclo de inferencia en dos servicios distintos:

Pod de prefill. Recibe el prompt, ejecuta el prefill, produce el KV cache. Hardware: GPUs con alto compute (H100, H200, B200). Optimizado para batching agresivo y throughput, no para latencia individual: si llegan 32 prompts en 100 ms, los procesa juntos.

Pod de decode. Recibe el KV cache ya construido, ejecuta la generación token a token, streamea al cliente. Hardware: GPUs con buen bandwidth pero idealmente más baratas por TFLOPS (RTX 4090, L40S, A100, incluso A30 según el caso). Optimizado para latencia por token (TBT bajo).

Entre ambos: una transferencia de KV cache sobre la red, que puede ser nodo-local (shared memory, NVLink), intra-rack (RDMA con InfiniBand o RoCE) o cross-rack (NIXL sobre UCX). El coste de esta transferencia escala linealmente con la longitud del contexto, y es la clave económica del esquema.

Monolítico (aggregated)GPU únicascheduler decide cada ciclo:prefilldecodeinterferencia en cada cambio→ TBT sube cuando llega prefilluna HW óptima para ambos:imposibleDisaggregatedpod prefillH100 / H200 / B200compute alto, batchingagresivopod decode4090 / L40S / A100bandwidth alto, TBTestableKV cacheNIXL/RDMArouter (vLLM/Dynamo)distribuye prompts y streams→ TBT estable, TTFT bajocoste: transferencia KV cache~5-50 ms según interconnect

El protocolo de transferencia: la economía del movimiento

El KV cache transferido en un Llama 3 70B con 4K de contexto pesa aproximadamente 2,6 GB (80 layers × 8 KV heads × 128 dim × 4 096 tokens × 2 (K y V) × 2 bytes en BF16). Mover 2,6 GB entre dos GPUs no es trivial:

CanalBandwidth efectivoTiempo para 2,6 GB
NVLink intra-nodo (NVSwitch)~450 GB/s~6 ms
Shared memory (mismo nodo, PCIe 5)~60 GB/s~45 ms
RDMA InfiniBand 400 Gbps~50 GB/s~55 ms
RDMA RoCE 200 Gbps~25 GB/s~105 ms
TCP/IP 10 GbE~1 GB/s~2,6 s

Lectura inmediata: por encima de InfiniBand-grade, la transferencia es cómoda. Por debajo, lleva al traste el TTFT que estamos intentando mejorar. Disaggregated serving es viable sólo con interconexión decente — no es un patrón para clusters montados con switches Ethernet de consumo.

NVIDIA respondió a esto con NIXL (NVIDIA Inference Transfer Library), publicada a mediados de 2025: una librería que abstrae el transporte (UCX, NCCL, RDMA verbs directos, shared memory) y elige el mejor camino disponible automáticamente. vLLM la integra desde finales de 2025 mediante el NixlConnector. Es ahora el default de facto para nuevos despliegues.

Implementaciones reales en mayo 2026

El recorrido del patrón en dos años:

2024 ene  · DistServe (HKU + UCSD): 7,4× requests al mismo SLO
2024 may  · SplitWise (Microsoft): variante con hardware heterogéneo
2024 dic  · vLLM disagg experimental (SharedStorage + PyNcclConnector)
2025 mar  · NIXL release (NVIDIA): librería de transferencia unificada
2025 jul  · vLLM NixlConnector estable
2025 nov  · SGLang, llm-d, MoonCake adoptan el patrón
2026 mar  · NVIDIA Dynamo 1.0 GA (GTC 2026): production-ready a escala datacenter

A día de hoy, el patrón es el default en cualquier framework de serving serio. Los que siguen monolíticos son los pequeños o los educativos.

Tres opciones realistas para una infraestructura on-premise:

  1. vLLM disagg con NixlConnector. El camino más abierto, requiere desplegar dos sets de pods de vLLM (uno con --kv-transfer-config '{"kv_role":"producer"}', otro con "kv_role":"consumer") y un proxy router. Suficiente para clusters de 4-16 GPUs.
  2. SGLang con disagg. Equivalente conceptual, mejor performance en algunos workloads MoE.
  3. NVIDIA Dynamo 1.0. El que se está imponiendo a escala datacenter. Cubre routing, KV cache management, monitorización y scheduling en un solo plano de control. Más pesado, pero la solución de referencia si tu cluster crece por encima de 32 GPUs.

Los números que importan

Lo que la disaggregation desbloquea, en términos directos:

MétricaAggregated (monolítico)DisaggregatedMejora
Goodput (req/s al SLO)baseline1,4 – 2×hasta 2×
TTFT bajo carga altasube agresivo desde QPS 4estable hasta QPS 7+~2×
Request rate al mismo SLO (DistServe paper)baseline7,4×7,4×
Throughput MoE en Blackwell (Dynamo, GB300 NVL72)baseline (Hopper)hasta 50×depende del modelo
Coste por token (heterogéneo H100 + commodity)baseline (todo H100)-48 %casi mitad

Hay que leer estos números con cuidado: los más espectaculares (7× y 50×) requieren hardware específico (Blackwell GB200/GB300 NVL72) y modelos específicos (MoE grandes). El rango realista para un on-premise típico es 1,4-2× en goodput y -30 a -50 % en coste por token, dependiendo de cuán heterogénea sea la mezcla de GPUs y de cuán optimizada esté la transferencia de KV cache.

Heterogeneidad: la versión radical

El paso lógico siguiente, propuesto por SplitWise en 2024 y madurado en 2025-2026 (Cronus, Tessera y otros), es mezclar tipos de GPU: GPUs caras de cómputo alto para prefill, GPUs commodity con buen bandwidth para decode.

Coste indicativo (precios de mercado típicos a mediados de 2026):

  • H100 SXM: ~30-40 k$ capex, ~3-4 $/h amortizado. Perfil compute-pesado.
  • L40S: ~8-10 k$ capex, ~1,5 $/h. Perfil intermedio, 864 GB/s de bandwidth.
  • RTX 4090: ~1,5 k$ capex, ~0,30 $/h. Perfil compute-modesto pero 1 TB/s de bandwidth GDDR6X — suficiente para decode de modelos hasta ~30B parámetros.

Un cluster mixto realista para servir un modelo 8B:

2× RTX 4090 (prefill batch)   →  ~3.000 $ capex, ~0,60 $/h
4× RTX 4090 (decode pool)     →  ~6.000 $ capex, ~1,20 $/h
TOTAL                         →  ~9.000 $ capex, ~1,80 $/h

Frente a la alternativa monolítica equivalente en throughput:

2× H100 SXM (todo en uno)     →  ~70.000 $ capex, ~7 $/h

El mismo throughput a una fracción del capex y a la cuarta parte del coste por hora, a costa de complejidad operativa: ahora tienes dos pools que coordinar, una red de transferencia que cuidar, y un scheduler que no es trivial.

Para modelos más grandes (Llama 3 70B), el decode pool ya no cabe en una 4090 individual (el modelo no entra en 24 GB ni siquiera cuantizado a INT4 con margen). Ahí la mezcla razonable es H100 para prefill + L40S o A100 80GB para decode, con ahorro típico del 30-40 % sobre la opción todo-H100.

Aplicado a hardware on-premise típico

Caso 1 — Una o dos RTX 4090: monolítico sigue ganando

Con una sola GPU no hay disaggregation que valga: el patrón requiere mínimo dos GPUs en pods separados. Con dos 4090, técnicamente puedes intentarlo (una para prefill, otra para decode con KV cache transferido por PCIe 5 o RDMA básico), pero el overhead de transferencia se come la ganancia para modelos pequeños donde el prefill ya es rápido.

Recomendación: mantener monolítico (vLLM tradicional, bien configurado con KV cache cuantizado). El siguiente nivel justificable de complejidad es un cluster con interconexión rápida.

Configuración mínima realista para disaggregation seria, sirviendo un modelo 70B en producción:

2× H100 (TP=2)            →  2 pods de prefill
2× H100 (TP=2)            →  pods de decode con varias instancias compartiendo TP
NIXL sobre NVLink         →  transferencia KV cache <6 ms
Router (vLLM o Dynamo)    →  distribución de prompts y stream

Resultado realista esperado: goodput 1,6-1,9× respecto al mismo cluster en monolítico, con TTFT estable hasta cargas de QPS 7-8 (frente al QPS 4 al que empieza a degradar el monolítico).

Si la mezcla heterogénea es posible (añadir 4-8 L40S al cluster para hacer el decode pool), el coste por token cae adicionalmente entre un 25 % y un 35 %, manteniendo el modelo 70B servido íntegro.

Posición dentro de la arquitectura

Disaggregated serving es una capa transversal a casi todo lo discutido en artículos previos. Toca:

  • El KV cache porque es el artefacto que se transfiere entre pods. Sin entender bien cuánto pesa el cache y cómo crece con el contexto, no se puede dimensionar la transferencia.
  • El fine-tuning continuo porque el multi-LoRA hot-swap conserva su semántica: cada pod (prefill o decode) carga los adapters por separado, y el router decide qué adapter aplicar en cada fase.
  • La topología del cluster: cambia la HW recomendada, el networking exigido y el modelo de costes.

Si estás diseñando una infraestructura de inferencia para 2026 desde cero, disaggregation deja de ser opcional para cualquier cluster que exceda 4 GPUs de capacidad. Si estás modernizando una existente, es la actualización con mejor retorno por euro invertido — siempre que el networking entre pods sea decente (NVLink intra-nodo o RDMA intra-rack como mínimo).

Lo que no hemos cubierto (próximos artículos)

  • NIXL en detalle: cómo elige el transporte óptimo, cómo se configura UCX, qué pasa cuando RDMA falla y hay que degradar a TCP.
  • Scheduler de routing: cómo decide el orquestador qué pod recibe qué petición, batching dinámico, manejo de prioridades.
  • Multi-tenant disagg: aislamiento de KV cache entre tenants, ACLs por adapter, multi-LoRA sobre pods especializados.
  • Disagg + prefix caching: cómo se combina con el patrón de reutilización de KV cache cuando varios prompts comparten prefijo (system prompt común).
  • Disagg en edge / inferencia local: viabilidad sobre hardware doméstico (4090 + Mac Studio, por ejemplo), donde la transferencia depende de Thunderbolt o Ethernet residencial.

Ver también

Referencias