Blog - Jorge Rodriguez Flores
← Volver al blog

La Arquitectura de Netflix: Cómo Escala a 300 Millones de Usuarios

netflix microservicios aws arquitectura escalabilidad streaming
Compartir: X / Twitter LinkedIn
La Arquitectura de Netflix: Cómo Escala a 300 Millones de Usuarios

Netflix es uno de los casos de estudio más citados en la industria tecnológica cuando se habla de arquitecturas a escala masiva. Con más de 300 millones de suscriptores en 190 países, transmitiendo más de 1.000 millones de horas de contenido por semana, su infraestructura enfrenta desafíos que pocas organizaciones en el mundo han tenido que resolver. En este artículo exploramos en detalle las decisiones arquitectónicas, tecnologías y patrones que hacen posible que Netflix funcione con una disponibilidad cercana al 100%.

De Monolito a Microservicios: La Gran Migración

La historia de la arquitectura de Netflix es, en gran parte, la historia de cómo migrar un monolito a microservicios a escala. En 2008, Netflix sufrió una corrupción grave de base de datos que dejó el servicio offline durante tres días. Ese incidente fue el catalizador que llevó a la compañía a repensar completamente su arquitectura.

La decisión fue clara: abandonar el datacenter propio y migrar completamente a la nube, adoptando al mismo tiempo una arquitectura de microservicios. La migración a AWS tomó aproximadamente 7 años (2008-2016) y es considerada una de las migraciones cloud más ambiciosas jamás ejecutadas.

Hoy, Netflix opera más de 1.000 microservicios desplegados en AWS, cada uno con su propio equipo, ciclo de deployment y stack tecnológico. La filosofía es simple: equipos pequeños y autónomos que poseen servicios pequeños y bien definidos.

La Infraestructura en AWS: Tres Regiones Activas

Netflix opera en un modelo multi-región activo-activo, principalmente en tres regiones de AWS: us-east-1 (North Virginia), us-west-2 (Oregon) y eu-west-1 (Irlanda). Esto significa que las tres regiones están sirviendo tráfico simultáneamente, no en modo primario-secundario.

Los servicios principales de AWS que utiliza Netflix incluyen:

  • EC2: Miles de instancias para ejecutar microservicios, con Auto Scaling Groups que ajustan la capacidad según la demanda.
  • S3: Almacenamiento de assets, configuraciones, datos de analítica y artefactos de deployment.
  • DynamoDB: Base de datos NoSQL para datos de baja latencia como historial de visualización, preferencias y estado de sesión.
  • ElastiCache (Memcached/Redis): Caché distribuida para reducir la carga en bases de datos y acelerar las respuestas.
  • SQS / Kinesis: Mensajería y streaming de eventos para comunicación asíncrona entre servicios.
  • Route 53: DNS con failover automático entre regiones.
Arquitectura Multi-Región de Netflix:

         ┌─────────────┐    ┌─────────────┐    ┌─────────────┐
         │  us-east-1  │    │  us-west-2  │    │  eu-west-1  │
         │  (Virginia) │    │  (Oregon)   │    │  (Irlanda)  │
         └──────┬──────┘    └──────┬──────┘    └──────┬──────┘
                │                  │                  │
         ┌──────▼──────────────────▼──────────────────▼──────┐
         │              Global Load Balancer                  │
         │         (Route 53 + Latency Routing)               │
         └───────────────────────────────────────────────────┘
                              │
                    ┌─────────▼─────────┐
                    │   Netflix CDN     │
                    │   (Open Connect)  │
                    └───────────────────┘
                              │
                    ┌─────────▼─────────┐
                    │    ISP / Usuario   │
                    └───────────────────┘

Open Connect: La CDN Propia de Netflix

Uno de los aspectos más singulares de la arquitectura de Netflix es que construyeron su propia CDN (Content Delivery Network) llamada Open Connect, en lugar de usar servicios como Cloudflare o Akamai para el contenido de video.

Open Connect consiste en miles de servidores de almacenamiento y entrega de video (OCAs - Open Connect Appliances) instalados directamente en los datacenters de los ISPs y puntos de intercambio de tráfico (IXPs) alrededor del mundo. Netflix ofrece estos servidores gratuitamente a los ISPs a cambio de colocarlos en su infraestructura.

El resultado es extraordinario: más del 95% del tráfico de Netflix se sirve directamente desde OCAs locales, sin pasar por internet público. Esto reduce la latencia, mejora la calidad del video y reduce los costos de ancho de banda tanto para Netflix como para los ISPs.

Cómo funciona el pre-poblado de OCAs

Durante las horas de baja demanda (madrugada), Netflix pre-copia proactivamente el contenido más popular hacia los OCAs más cercanos a los usuarios. Este proceso se llama proactive caching y usa algoritmos de machine learning para predecir qué contenido será más demandado en cada región.

# Pseudocódigo simplificado del algoritmo de pre-caching
def calcular_contenido_para_precargar(region, fecha):
    # Obtener historial de visualizaciones de los últimos 7 días
    historial = obtener_historial_region(region, dias=7)

    # Predecir popularidad para el día siguiente
    popularidad_predicha = modelo_ml.predict(
        historial=historial,
        dia_semana=fecha.weekday(),
        eventos_especiales=calendario_eventos(fecha),
        tendencias_globales=obtener_tendencias_globales()
    )

    # Filtrar por contenido no disponible en OCA local
    oca_inventory = obtener_inventario_oca(region)
    candidatos = [
        item for item in popularidad_predicha
        if item.content_id not in oca_inventory
        and item.score > THRESHOLD_MINIMO
    ]

    # Ordenar por score y limitar al espacio disponible en disco
    espacio_disponible = obtener_espacio_oca(region)
    return seleccionar_por_espacio(candidatos, espacio_disponible)

El Stack de Microservicios: Eureka, Zuul y Hystrix

Netflix no solo usa microservicios, sino que construyó y publicó como open source el ecosistema de herramientas que los hace posibles a escala. Estas herramientas, conocidas colectivamente como Netflix OSS, revolucionaron la industria y se convirtieron en la base de Spring Cloud.

Eureka — Service Discovery

Con más de 1.000 microservicios, la pregunta fundamental es: ¿cómo sabe el Servicio A dónde está el Servicio B? La respuesta es Eureka, el registro de servicios de Netflix.

Cada microservicio se registra en Eureka al arrancar, indicando su nombre, dirección IP, puerto y estado de salud. Cuando el Servicio A necesita llamar al Servicio B, pregunta a Eureka por las instancias disponibles y obtiene una lista de IPs.

// Microservicio registrándose en Eureka (Spring Boot)
@SpringBootApplication
@EnableEurekaClient
public class RecommendationServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(RecommendationServiceApplication.class, args);
    }
}

// application.yml
eureka:
  client:
    serviceUrl:
      defaultZone: http://eureka-server:8761/eureka/
  instance:
    preferIpAddress: true
    lease-renewal-interval-in-seconds: 10
    lease-expiration-duration-in-seconds: 30

spring:
  application:
    name: recommendation-service

Zuul — API Gateway

Zuul es el API Gateway de Netflix. Todo el tráfico externo entra por Zuul, que actúa como punto único de entrada y se encarga de:

  • Enrutamiento dinámico hacia los microservicios correctos
  • Autenticación y autorización de requests
  • Rate limiting y throttling
  • Canary deployments (enviar un % del tráfico a nuevas versiones)
  • Logging centralizado de todas las peticiones
  • Transformación de requests y respuestas
// Filtro de Zuul para autenticación
@Component
public class AuthenticationFilter extends ZuulFilter {

    @Override
    public String filterType() {
        return FilterConstants.PRE_TYPE; // Ejecutar antes del routing
    }

    @Override
    public int filterOrder() {
        return 1; // Prioridad alta
    }

    @Override
    public boolean shouldFilter() {
        RequestContext ctx = RequestContext.getCurrentContext();
        String path = ctx.getRequest().getRequestURI();
        // Excluir endpoints públicos
        return !path.startsWith("/public/");
    }

    @Override
    public Object run() {
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();

        String token = request.getHeader("Authorization");
        if (token == null || !tokenValidator.isValid(token)) {
            ctx.setSendZuulResponse(false);
            ctx.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value());
            ctx.setResponseBody("{\"error\": \"Unauthorized\"}");
        }
        return null;
    }
}

Hystrix — Circuit Breaker

En un sistema con 1.000 microservicios, los fallos en cascada son el mayor riesgo. Si el Servicio A llama al Servicio B que llama al Servicio C, y C falla, B puede quedar bloqueado esperando respuesta, lo que bloquea a A, que bloquea a quien lo llama... y así el fallo se propaga por todo el sistema.

Hystrix implementa el patrón Circuit Breaker: si un servicio falla repetidamente, Hystrix abre el circuito y las llamadas posteriores fallan inmediatamente (en lugar de esperar timeout), dando tiempo al servicio afectado para recuperarse.

// Llamada protegida con Hystrix
@Service
public class RecommendationClient {

    @HystrixCommand(
        fallbackMethod = "getDefaultRecommendations",
        commandProperties = {
            @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "20"),
            @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "50"),
            @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "5000"),
            @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "1000")
        }
    )
    public List getRecommendations(String userId) {
        return recommendationService.getPersonalized(userId);
    }

    // Fallback: devolver recomendaciones genéricas si el servicio falla
    public List getDefaultRecommendations(String userId) {
        return contentService.getTrending(limit=20);
    }
}

// Estados del Circuit Breaker:
// CLOSED (normal) → OPEN (fallo detectado) → HALF-OPEN (probando recuperación)

Resiliencia Caótica: Chaos Engineering con Chaos Monkey

Netflix adoptó una filosofía radical ante los fallos: en lugar de intentar evitarlos, los practican deliberadamente en producción. Esta práctica, conocida como Chaos Engineering, fue pionera en la industria y Netflix publicó las herramientas con las que la implementan bajo el nombre de Simian Army.

Chaos Monkey

Chaos Monkey es el más famoso: un servicio que aleatoriamente termina instancias EC2 en producción durante el horario laboral. La lógica es que si los ingenieros saben que cualquier instancia puede morir en cualquier momento, diseñarán sistemas que se recuperen automáticamente de esos fallos.

# Configuración de Chaos Monkey (versión moderna con Chaos Toolkit)
steady-state-hypothesis:
  title: "El servicio de recomendaciones responde correctamente"
  probes:
    - type: http
      name: recommendation-service-health
      url: http://recommendation-service/health
      timeout: 3
      expected_status: 200

method:
  - type: action
    name: terminate-random-instance
    provider:
      type: python
      module: chaosaws.ec2.actions
      func: terminate_instances
      arguments:
        filters:
          - name: "tag:Service"
            values: ["recommendation-service"]
          - name: "instance-state-name"
            values: ["running"]
        count: 1  # Matar 1 instancia aleatoria

rollbacks:
  - type: action
    name: wait-for-autoscaling
    provider:
      type: python
      module: chaosaws.asg.actions
      func: wait_for_desired_instances
      arguments:
        asg_names: ["recommendation-service-asg"]

Otros miembros del Simian Army

  • Latency Monkey: Introduce latencia artificial en las llamadas entre servicios para probar la tolerancia a slowdowns.
  • Conformity Monkey: Detecta instancias que no siguen las mejores prácticas de AWS y las termina.
  • Security Monkey: Monitorea configuraciones de seguridad de AWS (grupos de seguridad, IAM) y alerta de violaciones.
  • Chaos Gorilla: Simula la caída de una zona de disponibilidad completa de AWS.
  • Chaos Kong: Simula la caída de una región completa de AWS.

Personalización a Escala: Machine Learning y el Sistema de Recomendaciones

Netflix estima que más del 80% del contenido que se ve en su plataforma proviene de recomendaciones algorítmicas, no de búsquedas directas. El sistema de recomendaciones es, por tanto, uno de los activos más valiosos de la compañía.

Arquitectura del sistema de recomendaciones

El sistema opera en dos fases:

  1. Offline (batch): Entrenamiento de modelos con el historial completo de visualizaciones. Se ejecuta en Apache Spark sobre grandes clusters EMR de AWS, procesando petabytes de datos de comportamiento de usuarios.
  2. Online (real-time): Inferencia en tiempo real para generar las recomendaciones personalizadas que ve cada usuario al abrir Netflix. Usa los modelos pre-entrenados con datos actualizados de sesión.
# Arquitectura simplificada del pipeline de recomendaciones

# 1. OFFLINE: Entrenamiento en Spark (corre nocturnamente)
from pyspark.ml.recommendation import ALS
from pyspark.sql import SparkSession

spark = SparkSession.builder.appName("NetflixRecommendations").getOrCreate()

# Cargar historial de visualizaciones desde S3
ratings = spark.read.parquet("s3://netflix-data/viewing-history/")

# Entrenar modelo ALS (Alternating Least Squares)
als = ALS(
    maxIter=15,
    regParam=0.1,
    userCol="userId",
    itemCol="contentId",
    ratingCol="implicitRating",
    coldStartStrategy="drop",
    implicitPrefs=True  # Datos implícitos (tiempo de visualización)
)

model = als.fit(ratings)

# Guardar modelo y factores de usuario/item en S3
model.save("s3://netflix-models/als/latest/")
model.userFactors.write.parquet("s3://netflix-models/user-factors/")
model.itemFactors.write.parquet("s3://netflix-models/item-factors/")

# 2. ONLINE: Servicio de inferencia en tiempo real
import numpy as np
from redis import Redis

class RecommendationService:
    def __init__(self):
        self.redis = Redis(host='elasticache-endpoint')
        self.item_factors = self.load_item_factors_from_cache()

    def get_recommendations(self, user_id: str, n: int = 20) -> list:
        # Obtener vector de usuario desde Redis (cacheado)
        user_vector = self.redis.get(f"user_factor:{user_id}")

        if user_vector is None:
            # Usuario nuevo: usar recomendaciones de trending
            return self.get_trending(n)

        user_vec = np.frombuffer(user_vector, dtype=np.float32)

        # Calcular similitud coseno con todos los items
        scores = self.item_factors @ user_vec

        # Obtener top-N, excluyendo ya vistos
        watched = self.get_watched_content(user_id)
        top_items = [
            item_id for item_id in np.argsort(scores)[::-1]
            if item_id not in watched
        ][:n]

        return top_items

Artwork personalizado

Uno de los detalles más sorprendentes de la personalización de Netflix es que la imagen de portada de cada título es diferente para cada usuario. Los algoritmos de ML determinan qué artwork tiene más probabilidad de hacer clic a un usuario específico basándose en su historial de visualización. Una misma película puede mostrar una imagen diferente a un usuario que ve acción y a uno que ve romances.

Observabilidad: Atlas, Mantis y Spectator

Con 1.000 microservicios generando millones de métricas por segundo, la observabilidad es crítica. Netflix construyó su propio stack de monitorización:

Atlas — Métricas en tiempo real

Atlas es el sistema de métricas de series temporales de Netflix, diseñado para manejar millones de métricas por segundo. A diferencia de soluciones como Prometheus, Atlas fue diseñado desde el inicio para escalar a nivel de Netflix y soporta consultas complejas con su propio lenguaje de query.

# Consulta Atlas para ver error rate de un servicio
# por región en los últimos 5 minutos

name,http.requests,:eq,
status,5xx,:re,
:and,
:sum,
(,region,),
:by,
5,
:offset,
:pct-change

Mantis — Stream processing de eventos

Mantis es la plataforma de stream processing de Netflix que permite analizar eventos en tiempo real. Los equipos pueden crear jobs que suscriben a streams de eventos de cualquier microservicio y ejecutan análisis en tiempo real: detección de anomalías, alertas, dashboards en vivo.

Spectator — Librería de instrumentación

Spectator es la librería que todos los microservicios de Netflix usan para emitir métricas. Abstrae el backend de métricas (Atlas, Prometheus, etc.) y proporciona tipos de métricas de alto nivel:

// Instrumentación con Spectator en un microservicio Java
@Service
public class RecommendationService {

    private final Registry registry;
    private final Timer recommendationTimer;
    private final Counter errorCounter;
    private final DistributionSummary resultSizeSummary;

    public RecommendationService(Registry registry) {
        this.registry = registry;
        this.recommendationTimer = registry.timer("recommendation.latency",
            "service", "recommendation-service",
            "region", System.getenv("AWS_REGION")
        );
        this.errorCounter = registry.counter("recommendation.errors",
            "service", "recommendation-service"
        );
        this.resultSizeSummary = registry.distributionSummary(
            "recommendation.result.size"
        );
    }

    public List getRecommendations(String userId) {
        return recommendationTimer.record(() -> {
            try {
                List results = fetchRecommendations(userId);
                resultSizeSummary.record(results.size());
                return results;
            } catch (Exception e) {
                errorCounter.increment();
                throw e;
            }
        });
    }
}

Deployment: Spinnaker y el Modelo de Entrega Continua

Netflix hace cientos de deployments al día a través de sus microservicios. Esto es posible gracias a Spinnaker, la plataforma de entrega continua multi-cloud que desarrollaron y publicaron como open source en 2015.

Spinnaker abstrae los detalles de los diferentes proveedores cloud (AWS, GCP, Azure, Kubernetes) y proporciona un modelo de deployment declarativo con capacidades avanzadas:

  • Red/Black deployments: Crear un nuevo cluster idéntico (Black) con la nueva versión, cambiar el tráfico de Red a Black, y mantener Red en standby para rollback inmediato.
  • Canary Analysis: Enviar el 1% del tráfico a la nueva versión, comparar métricas automáticamente con la versión estable, y decidir si hacer rollout o rollback.
  • Pipeline gates: Puntos de aprobación manual o automática (basada en métricas) en el pipeline de deployment.
# Pipeline de Spinnaker para deployment de microservicio
pipeline:
  name: "Recommendation Service Deploy"
  stages:
    - name: "Bake AMI"
      type: bake
      region: us-east-1
      package: recommendation-service

    - name: "Deploy to Staging"
      type: deploy
      clusters:
        - account: netflix-staging
          region: us-east-1
          strategy: redblack
          capacity:
            min: 2
            max: 10
            desired: 4

    - name: "Run Integration Tests"
      type: runJob
      application: recommendation-service-tests

    - name: "Canary Analysis (1% traffic)"
      type: canaryAnalysis
      canaryConfig:
        lifetimeHours: 1
        successfulScore: 95
        unhealthyScore: 75
        canaryPercentage: 1

    - name: "Deploy to Production"
      type: deploy
      stageEnabled:
        type: expression
        expression: "${#stage('Canary Analysis').context.canaryScore > 95}"
      clusters:
        - account: netflix-prod
          regions: [us-east-1, us-west-2, eu-west-1]
          strategy: redblack

Lecciones Aprendidas y Principios Arquitectónicos

Después de más de una década construyendo y operando esta arquitectura, Netflix ha destilado una serie de principios que guían sus decisiones:

1. Diseña para el fallo

Asume que cualquier componente fallará en algún momento. Usa circuit breakers, timeouts, bulkheads y fallbacks en todas las dependencias externas. Si un servicio no puede degradar gracefully cuando una dependencia falla, está mal diseñado.

2. Prefiere la disponibilidad sobre la consistencia

En sistemas distribuidos a escala global, el teorema CAP obliga a elegir. Netflix elige disponibilidad: es mejor mostrar una lista de recomendaciones ligeramente desactualizada que no mostrar nada.

3. Ownership total de los equipos

Cada microservicio es propiedad de un equipo que lo construye, despliega, opera y da soporte 24/7. No hay un equipo de operaciones separado que gestione la infraestructura de otros. Esto alinea los incentivos: quien desarrolla es quien gestiona las alertas a las 3am.

4. Observabilidad antes de deployment

Antes de desplegar cualquier cambio, el equipo debe tener dashboards y alertas configuradas. No se puede operar lo que no se puede observar.

5. Chaos como práctica, no como accidente

La resiliencia no es algo que se verifica ocasionalmente: es algo que se practica continuamente. Los ejercicios de caos deben ser parte del ciclo de vida del software, no reacciones a incidentes.

Conclusión

La arquitectura de Netflix es el resultado de más de 15 años de evolución, fracasos, aprendizajes y reinvención continua. No surgió de un diseño perfecto en papel sino de la necesidad imperiosa de resolver problemas reales a escala masiva.

Lo más valioso de estudiar la arquitectura de Netflix no es copiarla literalmente — la mayoría de organizaciones no necesitan ni pueden operar 1.000 microservicios — sino entender los principios que la guían: ownership claro, tolerancia a fallos, observabilidad profunda, despliegue continuo y una cultura que trata los fallos como oportunidades de aprendizaje.

Netflix ha publicado como open source la gran mayoría de las herramientas que hacen posible su arquitectura: Eureka, Hystrix, Zuul, Spinnaker, Chaos Monkey, Atlas, Mantis y muchas más. Esta generosidad técnica ha influenciado profundamente la forma en que la industria construye sistemas distribuidos, convirtiendo a Netflix no solo en una compañía de entretenimiento sino en uno de los mayores contribuidores a la ingeniería de software moderna.

Artículos relacionados