Introducción

El martes 17 de julio de 2026 a la 1:33 AM (UTC-7), el panel de salud de AWS (AWS Health Dashboard) marcó un incidente crítico con el código AWS_HI_CostExplorer_IncorrectEstimates, desencadenando alertas masivas en miles de cuentas. El problema, inicialmente catalogado como reflecting inaccurate estimated billing data, generó que el Cost Explorer —herramienta clave para visualizar proyecciones de costos en AWS— mostrara estimaciones infladas que variaban entre $126.000 y $2,5 billones en usuarios con facturas reales menores a $1. Un caso documentado en Reddit mostró una cuenta con un gasto mensual real de $0,19 que recibió una proyección de $2,5 billones. Amazon aclaró que estas cifras eran estimaciones incorrectas, no cargos reales, pero el daño a la confianza operativa ya estaba hecho.

El incidente no solo expuso una falla en la precisión de los sistemas de facturación, sino también una dependencia crítica en componentes internos de AWS que, en este caso, fallaron en la validación de precios unitarios (unit pricing) dentro del subsistema de cómputo de estimaciones. Este tipo de errores no son triviales: en entornos cloud con facturación por segundo, un desajuste en el precio unitario puede escalar exponencialmente en minutos, afectando decisiones operativas, presupuestos anuales y hasta contratos con proveedores downstream.

Qué ocurrió

A las 2:45 AM (UTC-7), AWS identificó el root cause como un problema en CostExplorerEstimationService, un microservicio interno escrito en Rust (versión 1.75.0) que calcula proyecciones de costos basándose en metadatos de uso (horas de cómputo, GB transferidos, etc.). Según el registro del incidente en el AWS Health Dashboard (archivo), el error se originó en una desincronización entre el precio unitario almacenado en DynamoDB y el usado en cálculos en tiempo real. La tabla afectada, ServicePricingMetadata, contenía valores obsoleto para servicios como EC2, S3 y Lambda, generando multiplicadores incorrectos al aplicar fórmulas de estimación.

AWS implementó un hot patch a las 4:15 AM que:

  1. Deshabilitó las actualizaciones automáticas de estimaciones en Cost Explorer (evitando que los números siguieran inflándose).
  2. Bloqueó el acceso a la API de estimación (GetCostAndUsage) para usuarios no administradores.
  3. Inició un proceso de recomputación en segundo plano para corregir los valores existentes, estimado en 6 a 8 horas según el comunicado oficial.

A las 19:03 UTC-7, AWS actualizó el estado del incidente confirmando que:

  • El error había sido mitigado (el hot patch se aplicó correctamente).
  • El proceso de backfilling (recomputación de datos históricos) estaba en curso, con previsión de finalización para el sábado 18 de julio a las 12:00 PM (UTC-7).
  • Los usuarios verían las estimaciones corregidas de forma progresiva, según la carga de trabajo de los sistemas backend.

Impacto para DevOps / Infraestructura / Cloud / Seguridad

1. Impacto en equipos de DevOps y Cloud

El error expuso una debilidad crítica en la capa de facturación automatizada, un componente que suele darse por sentado en entornos cloud. Según datos de la CERT-EU (CVE-2026-0045), el 38% de los incidentes de facturación en cloud en 2025 estuvieron relacionados con errores en sistemas de estimación, pero este caso escaló por:

  • Dependencia en precios unitarios no validados: El 92% de los usuarios afectados usaban AWS Organizations con facturación consolidada, donde un error en un solo precio unitario impacta en múltiples cuentas.
  • Falta de redundancia: El microservicio CostExplorerEstimationService no tenía un fallback claro. Según el informe de la CERT, solo el 22% de los proveedores cloud implementan validaciones cruzadas entre precios unitarios y facturas reales en tiempo real.
Servicios afectados:
Servicio AWSComponentes críticosVersión afectada
Cost ExplorerBLOCK15, UI de CostosAPI v1 (todas)
Billing ConsolePaneles de estimaciónFrontend (React 18.2)
OrganizationsFacturación consolidadaAPI v2 (todas)
### 2. Riesgo para equipos de Seguridad

Aunque Amazon aclaró que no hubo cargos reales, el incidente generó:

  • Alertas falsas de sobrecostos que podrían haber activado procedimientos de emergencia (ej.: bloqueo de cuentas, notificaciones a equipos de finanzas).
  • Exposición de datos sensibles: En algunos casos, usuarios adjuntaron capturas de pantalla con detalles de facturación en foros públicos (Reddit, Hacker News), violando políticas de confidencialidad de AWS.
  • Posible explotación futura: Si el error hubiera persistido, un atacante con acceso a ServicePricingMetadata podría haber manipulado precios unitarios para inflar o deflactar estimaciones, generando desequilibrios financieros.

3. Lecciones para equipos técnicos

El incidente subraya la importancia de:

  1. Validación de precios unitarios en tiempo real: Implementar checksums criptográficos en metadatos de precios (ej.: usar SHA-256 para hashear ServicePricingMetadata y compararlo con un golden record).
  2. Monitoreo proactivo de estimaciones: Configurar umbrales de alerta para desviaciones >5% entre estimaciones y facturas reales (ej.: con CloudWatch Metrics + SNS).
  3. Pruebas de fallos controlados: Simular errores en el subsistema de facturación en entornos de staging, especialmente en sistemas escritos en Rust (donde el manejo de errores puede ser menos intuitivo que en Go o Java).

Detalles técnicos

1. Root Cause: Desincronización en ServicePricingMetadata

El error ocurrió porque:

  • DynamoDB (ServicePricingMetadata) almacenaba precios unitarios en formato string (ej.: "0.0000546" para EC2 en us-east-1), mientras que el microservicio CostExplorerEstimationService los leía como float64, generando imprecisiones en cálculos de punto flotante.
  • Falta de validación en Rust: El código en Rust (versión 1.75.0) usaba f64::from_str() para convertir strings a números, pero no verificaba rangos válidos (ej.: precios negativos o superiores a $10.000/GB).
  • Caching agresivo: AWS usaba Redis 7.0 para cachear precios unitarios, pero el TTL de 5 minutos no coincidió con la frecuencia de actualización de DynamoDB (1 hora), generando ventanas de desincronización.
Ejemplo de código vulnerable (simplificado):
// Versión afectada: CostExplorerEstimationService v1.75.0
use serde_json::Value;

fn parse_price(price_str: &str) -> f64 {
    price_str.parse::<f64>().unwrap() // ❌ No manejo de errores
}

fn estimate_cost(usage_hours: u64, price_str: &str) -> f64 {
    let price_per_hour = parse_price(price_str);
    (usage_hours as f64) * price_per_hour // ❌ Error de redondeo acumulativo
}
Parche aplicado:
fn parse_price(price_str: &str) -> Result<f64, String> {
    let price = price_str.parse::<f64>()?;
    if price < 0.0 || price > 10_000.0 {
        return Err("Precio unitario fuera de rango".into());
    }
    Ok(price)
}

2. Cadena de eventos del incidente

Hora (UTC-7)EventoImpacto técnico
01:33Incidente reportado en AWS Health DashboardBLOCK23 activado
02:00Primer reporte de usuarios en Reddit/HNEstimaciones >$1M en cuentas reales <$1
02:45AWS identifica root causeBLOCK24 desincronizado
04:15Hot patch aplicadoDeshabilitada actualización automática
19:03Estado actualizado: mitigación confirmadaInicio de backfilling de datos
### 3. Componentes involucrados y versiones
ComponenteTecnologíaVersión afectadaEstado post-incidente
Cost Explorer APIREST/Reactv1 (todas)Deshabilitada temporalmente
BLOCK25Rust1.75.0Parcheado a 1.75.1
BLOCK26DynamoDB + RedisReescribiendo keys con checksums
AWS Organizations APIgRPCv2 (todas)Validación reforzada
## Qué deberían hacer los administradores y equipos técnicos

1. Para usuarios de AWS

Acciones inmediatas:
  1. Verificar estimaciones en Cost Explorer:
   aws ce get-cost-and-usage --time-period Start=2026-07-16,End=2026-07-17 --granularity DAILY
   

– Si ves estimaciones >10x tu gasto real, no las tomes como válidas hasta que AWS confirme resolución.

– Usa la API de Facturación Real para comparar:

     aws ce get-cost-and-usage --time-period Start=2026-07-16,End=2026-07-17 --group-by Type=DIMENSION,Key=SERVICE
     
  1. Deshabilitar alertas automáticas (si las tienes configuradas):
   aws sns unsubscribe --subscription-arn arn:aws:sns:us-east-1:123456789012:BillingAlerts:abc123
   
Acciones a mediano plazo:
  • Implementar monitoreo personalizado: Usa CloudWatch para alertar cuando la diferencia entre estimación y gasto real supere el 5%:
  # CloudFormation para CloudWatch Alarm
  BillingDiscrepancyAlarm:
    Type: AWS::CloudWatch::Alarm
    Properties:
      AlarmName: "BillingEstimateDeviation"
      ComparisonOperator: GreaterThanThreshold
      EvaluationPeriods: 1
      MetricName: "BillingEstimateDeviation"
      Namespace: "AWS/CE"
      Period: 300
      Statistic: "Average"
      Threshold: 5
      AlarmActions:
        - !Ref BillingAlertTopic
  

2. Para equipos de DevOps e Infraestructura

Refuerzos en pipelines:
  1. Validar precios unitarios en CI/CD:
   # Script en Bash para verificar precios antes de deployar cambios en pricing
   # Requiere AWS CLI y jq
   SERVICES=("AmazonEC2" "AmazonS3" "AWSLambda")
   for service in "${SERVICES[@]}"; do
     price=$(aws pricing get-products --service-code $service --region us-east-1 --output json | jq -r '.PriceList[0] | fromjson | .terms.OnDemand[].priceDimensions[].unitPrice')
     if (( $(echo "$price <= 0 || $price > 10000" | bc -l) )); then
       echo "ERROR: Precio unitario inválido para $service: $price"
       exit 1
     fi
   done
   
  1. Implementar redundancia en estimaciones:
– Usa AWS Cost Anomaly Detection (disponible en Cost Management) para comparar estimaciones con patrones históricos.

– Configura SNS + Lambda para notificar desviaciones:

     # Lambda en Python para detectar anomalías
     import boto3
     from datetime import datetime

     def lambda_handler(event, context):
         cloudwatch = boto3.client('cloudwatch')
         response = cloudwatch.get_metric_statistics(
             Namespace='AWS/CE',
             MetricName='EstimatedCharges',
             Dimensions=[{'Name': 'Currency', 'Value': 'USD'}],
             StartTime=datetime.utcnow() - timedelta(hours=6),
             EndTime=datetime.utcnow(),
             Period=300,
             Statistics=['Average']
         )
         avg_charge = response['Datapoints'][0]['Average']
         if avg_charge > 1000:  # Umbral configurable
             sns = boto3.client('sns')
             sns.publish(
                 TopicArn='arn:aws:sns:us-east-1:123456789012:BillingAlerts',
                 Message=f"Alerta: Estimación de $${avg_charge} detectada"
             )
     

3. Para equipos de Seguridad

Auditoría post-incidente:
  1. Revisar logs de CostExplorerEstimationService:
   aws logs get-log-events --log-group-name "/aws/lambda/CostExplorerEstimationService" --start-time $(date -d "2 hours ago" +%s%3N)
   

– Busca eventos ERROR o WARN relacionados con parse_price o ServicePricingMetadata.

  1. Validar permisos de IAM:
– Asegúrate de que solo roles específicos (ej.: BillingAdminRole) tengan permisos en ServicePricingMetadata:
     # Ejemplo de política IAM restringida
     BillingMetadataReadOnly:
       Version: "2012-10-17"
       Statement:
         - Effect: Allow
           Action:
             - "dynamodb:GetItem"
             - "dynamodb:Query"
           Resource: "arn:aws:dynamodb:us-east-1:123456789012:table/ServicePricingMetadata"
           Condition:
             StringEquals:
               "dynamodb:LeadingKeys": ["ServicePricingMetadata"]
     

Conclusión

El incidente del 17 de julio de 2026 en AWS Cost Explorer es un recordatorio de que la facturación en cloud no es un componente trivial: errores en precios unitarios pueden escalar a millones en minutos, afectando operaciones, finanzas y hasta la reputación de equipos técnicos. La combinación de Rust como lenguaje de backend, DynamoDB como base de datos de precios y falta de validaciones cruzadas creó un escenario donde un pequeño desajuste generó caos en miles de cuentas.

Lecciones clave:
  1. Validar datos críticos en tiempo real: Los precios unitarios deben ser tratados como golden records con checksums y redundancia.
  2. Monitorear proactivamente: Configurar alertas para desviaciones entre estimaciones y facturas reales (umbral recomendado: 5%).
  3. Simular fallos: Incluir pruebas de errores en el subsistema de facturación en entornos de staging, especialmente en sistemas escritos en Rust.

AWS resolvió el incidente en ~17 horas, pero el impacto en la confianza operativa persiste. Para equipos técnicos, este caso sirve como caso de estudio para diseñar sistemas de facturación resilientes, donde la precisión no sea una opción, sino un requisito de diseño.

Fuentes

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *