¿Por qué Migrar un Pipeline de Métricas?

Cuando operas una plataforma como Airbnb, las métricas son el sistema nervioso de tu infraestructura. Durante años, usaron StatsD con un sidecar Veneur — una configuración que funcionaba, pero mostraba su edad conforme la escala crecía. Los problemas eran clásicos: pérdida de paquetes UDP en alto throughput, tipos de histograma limitados y dependencia de un vendor.

El equipo decidió ir all-in en open source: OpenTelemetry (OTLP) para instrumentación y Prometheus para almacenamiento. Pero el abismo entre donde estaban y donde querían llegar era enorme. Esta es la historia de cómo cerraron esa brecha — sin romper producción.

La Estrategia de Dual-Write: No Migres, Paraleliza

Una de las lecciones más prácticas de esta migración es el enfoque de dual-write. En lugar de un corte riesgoso, Airbnb habilitó su biblioteca de métricas compartida para emitir tanto StatsD (al pipeline antiguo) como OTLP (al nuevo OTel Collector) simultáneamente. Esto permitió:

  • Validar la corrección comparando ambos flujos
  • Exponer cuellos de botella de escala temprano (y encontraron grandes)
  • Dejar que los usuarios migraran dashboards y alertas a su propio ritmo

Tip práctico: Si estás planeando una migración de métricas, empieza instrumentando emisión dual. Es más trabajo al principio, pero ahorra meses de apagón después.

La Sorpresa de Rendimiento del OTLP

Mientras la mayoría de los servicios manejaron el dual-write sin problemas, los emisores de mayor volumen (10K+ muestras/segundo por instancia) encontraron un muro. La presión de memoria se disparó, la actividad de GC aumentó y el heap creció. ¿El culpable? Temporalidad acumulativa en el SDK OTLP, que mantiene estado completo para cada combinación de etiqueta entre exportaciones.

El fix fue simple pero quirúrgico: cambiar esos servicios a temporalidad delta. El modo delta solo rastrea cambios entre exportaciones, reduciendo drásticamente la memoria en proceso. ¿El trade-off? Huecos en los datos si el servicio falla a medio intervalo. Para la mayoría de los servicios, el modo acumulativo se mantuvo; solo el 1% superior de emisores necesitó el cambio.

# Ejemplo: Configurando temporalidad delta para métricas de alta cardinalidad en SDK OTel Python
from opentelemetry.sdk.metrics import MeterProvider
from opentelemetry.sdk.metrics.export import AggregationTemporalitySelector

# Forzar delta para instrumentos específicos
delta_selector = AggregationTemporalitySelector.delta_preferred()
provider = MeterProvider(
    metric_readers=[...],
    aggregation_temporality_selector=delta_selector
)

Agregación Streaming a Escala Airbnb

Las métricas brutas son caras. Un solo pod emite miles de combinaciones de etiquetas (pod, hostname, región, etc.). Almacenarlas todas multiplicaría los costos por 10x. La solución: agregación streaming — quitar etiquetas de nivel de instancia antes del almacenamiento.

Airbnb evaluó varias opciones (reescritura de Veneur, recording rules, m3aggregator, OTel Collector, Vector) y eligió vmagent de VictoriaMetrics. ¿Por qué ganó vmagent?

CaracterísticavmagentAlternativas (OTel Collector, Vector, etc.)
Agregación streaming✅ Nativo❌ No soportado o experimental
Escalamiento horizontal via sharding✅ Config simple❌ Complejo o ausente
Tamaño del código~10K LOC (fácil de modificar)50K-100K+ LOC
DocumentaciónExcelenteVariable

La arquitectura usa dos capas de vmagents: routers (sin estado, hash de métricas por etiquetas) y aggregators (con estado, mantienen totales corrientes). Este diseño escaló a cientos de agregadores ingiriendo más de 100 millones de muestras por segundo.

Consejo práctico: Si estás construyendo un pipeline de métricas a escala, no subestimes el valor de una base de código pequeña y enfocada. Las ~10K líneas de vmagent hicieron fácil para Airbnb añadir características personalizadas como soporte para histogramas nativos y multitenencia estilo Mimir — y contribuir de vuelta upstream.

El Problema de los Contadores Dispersos (y el Fix Zero Injection)

Después de la migración, apareció un bug desagradable: las consultas PromQL usando rate() estaban consistentemente subcontando en comparación con el antiguo sistema StatsD.

La causa raíz es un caso borde conocido en la semántica de Prometheus. Cuando un contador se crea y se incrementa antes de que Prometheus lo scrapee, el incremento inicial se pierde. Para contadores de alta tasa, esto es insignificante, pero para contadores dispersos (ej.: requests por moneda por usuario por región — quizás 1 incremento por día), cada incremento importa.

Airbnb consideró varios workarounds (pre-inicializar todos los contadores, usar logs, emitir gauges, PromQL hacky), pero todos eran imprácticos. En su lugar, construyeron un fix transparente: zero injection en la capa de agregación.

Cómo Funciona Zero Injection

Cuando el agregador descarga un contador por primera vez, inyecta un cero sintético en lugar del valor real. El incremento real se retrasa un intervalo de descarga. Esto asegura que el rate() de Prometheus vea una línea base adecuada y no pierda el primer incremento.

# Pseudocódigo simplificado para la lógica de zero injection
class SparseCounterAggregator:
    def __init__(self):
        self.first_flush = True
        self.running_total = 0

    def flush(self):
        if self.first_flush:
            self.first_flush = False
            return 0  # inyecta cero
        else:
            value = self.running_total
            self.running_total = 0
            return value

El trade-off: el primer incremento se retrasa un intervalo de descarga (ej.: 10 segundos). Para contadores dispersos, eso es invisible. El beneficio: todos los contadores se inicializan implícitamente a cero, coincidiendo perfectamente con la semántica de Prometheus.

Por qué esto importa: Este fix es un gran ejemplo de resolver un problema en la capa correcta. En lugar de empujar complejidad a cada equipo escribiendo dashboards y alertas, Airbnb lo arregló una vez en el pipeline de agregación.

Limitaciones y Precauciones

  • Trade-off de temporalidad delta: Los servicios en modo delta pierden datos si fallan a medio intervalo. Esto es aceptable para servicios de alta cardinalidad, pero no para contadores críticos.
  • Retraso de zero injection: El primer incremento de cualquier contador se retrasa un intervalo de descarga. Para alertas en tiempo real en contadores nuevos, esto podría ser un problema.
  • Personalizaciones de vmagent: Los cambios de Airbnb en vmagent (histogramas nativos, multitenencia) requirieron conocimiento de Go. Si no te sientes cómodo modificando la base de código, podrías enfrentar limitaciones.
  • Complejidad del dual-write: Ejecutar dos pipelines simultáneamente duplica la sobrecarga operacional durante la migración. Planea una transición de varios meses.

¿Qué Sigue? Ruta de Aprendizaje

Si estás considerando una migración similar, aquí tienes tu ruta:

  1. Empieza pequeño: Elige un servicio con métricas de baja cardinalidad. Haz dual-write OTLP + StatsD por una semana. Valida que los conteos coincidan.
  2. Escala: Muévete a servicios de mayor volumen. Monitorea memoria y latencia. Cambia a temporalidad delta si es necesario.
  3. Construye agregación: Despliega vmagent (u otro agregador streaming) y prueba con un subconjunto de métricas.
  4. Maneja casos borde: Implementa zero injection o fixes similares para contadores dispersos. Prueba con dashboards reales.
  5. Corta: Cuando estés confiado, remueve el antiguo pipeline StatsD.

Para más sobre construcción de sistemas escalables, checa nuestro artículo sobre Por qué Airbnb Construyó su Propio Motor de Workflow Embutido. Y si buscas una forma rápida de prototipar automatización, mira cómo Construir un Agente Slack en Menos de 10 Minutos con la Nueva Skill de Agente Slack de Vercel.


Basado en el post original del blog de ingeniería por Eugene Ma y Natasha Aleksandrova en Airbnb. Todos los nombres de productos, logotipos y marcas son propiedad de sus respectivos dueños.

Airbnb observability team monitoring dashboard with Prometheus and OpenTelemetry metrics pipeline Development Concept Image

Este contenido fue redactado con la asistencia de herramientas de IA, basándose en fuentes confiables, y fue revisado por nuestro equipo editorial antes de su publicación. No reemplaza el asesoramiento de un profesional especializado.