Cómo configurar una alarma de facturación en AWS Free Tier con CloudWatch

Despertar con un cargo inesperado de AWS es uno de esos momentos que todo ingeniero recuerda. Si estás usando el Free Tier para experimentar o aprender, un solo servicio mal configurado — una instancia EC2 que olvidaste apagar, un NAT Gateway activo — puede generar cargos reales antes de que te des cuenta. Configurar una alarma de facturación en CloudWatch con un umbral de $5 es la red de seguridad mínima que deberías tener activa desde el primer día.

TL;DR: Alarma de facturación en AWS Free Tier

PasoAcciónHerramienta
1Habilitar métricas de facturación en la cuentaConsola de Billing / AWS CLI
2Crear un tema SNS para notificaciones por emailAWS CLI
3Confirmar la suscripción al emailBandeja de entrada
4Crear la alarma CloudWatch sobre la métrica EstimatedChargesAWS CLI
5Verificar que la alarma está activaAWS CLI

Cómo funciona la métrica EstimatedCharges en CloudWatch

Antes de crear cualquier alarma, es importante entender qué estás midiendo exactamente. CloudWatch expone la métrica EstimatedCharges en el namespace AWS/Billing. Esta métrica refleja el costo estimado acumulado del mes en curso, expresado en dólares USD. AWS la actualiza varias veces al día, no en tiempo real.

Hay una dependencia crítica que muchos pasan por alto: esta métrica no aparece en CloudWatch por defecto. Primero debes habilitar las métricas de facturación desde la configuración de Billing Preferences en tu cuenta raíz (o con permisos de facturación). Sin ese paso, la alarma que crees simplemente no tendrá datos y permanecerá en estado INSUFFICIENT_DATA indefinidamente.

Otro detalle importante: la métrica EstimatedCharges solo se publica en la región us-east-1, independientemente de dónde estén desplegados tus recursos. Todos los comandos CLI de CloudWatch para esta alarma deben ejecutarse contra esa región.

graph LR A["AWS Billing Service
cargos estimados del mes"] -->|"publica métrica
EstimatedCharges"| B["CloudWatch
namespace: AWS/Billing
región: us-east-1"] B -->|"evalúa umbral
cada 24h"| C{"¿Valor >= $5?"} C -->|"No"| D["Estado: OK"] C -->|"Sí"| E["Estado: ALARM"] E -->|"publica mensaje"| F["Tema SNS
billing-alarm-topic"] F -->|"entrega email"| G["Tu bandeja
de entrada"]
  1. Billing Service agrega los cargos estimados del mes y publica la métrica EstimatedCharges en CloudWatch (namespace AWS/Billing, región us-east-1).
  2. CloudWatch evalúa la alarma periódicamente comparando el valor de la métrica contra el umbral definido ($5 en este caso).
  3. Cuando el valor supera el umbral, CloudWatch transiciona la alarma al estado ALARM y publica una notificación al tema SNS.
  4. SNS entrega el mensaje a todos los suscriptores del tema — en este caso, tu dirección de email.

Paso 1: Habilitar métricas de facturación

Este paso debe realizarse desde la cuenta raíz de AWS o con una cuenta que tenga permisos de acceso a la consola de Billing. Sin esto, CloudWatch no recibirá datos de facturación y la alarma nunca se activará.

Navega a AWS Billing Console → Billing Preferences → Alert Preferences y activa la opción 'Receive CloudWatch Billing Alerts'. Guarda los cambios. Este ajuste puede tardar hasta 24 horas en comenzar a publicar métricas si la cuenta es nueva.

No existe un comando CLI directo para habilitar esta preferencia — debe hacerse desde la consola de Billing o mediante la API de Account Management. Si ya lo habilitaste anteriormente, puedes verificar que la métrica existe con:

aws cloudwatch list-metrics \
  --namespace AWS/Billing \
  --metric-name EstimatedCharges \
  --region us-east-1

Si el resultado está vacío, las métricas de facturación aún no están habilitadas o no se han publicado datos todavía.

Paso 2: Crear el tema SNS para notificaciones

SNS actúa como el canal de entrega. Primero creas el tema, luego suscribes tu email. La confirmación de la suscripción es obligatoria — SNS no entregará mensajes a un email no confirmado.

aws sns create-topic \
  --name billing-alarm-topic \
  --region us-east-1

El comando devuelve el ARN del tema. Anótalo, lo necesitarás en los pasos siguientes. Tendrá el formato:

arn:aws:sns:us-east-1:123456789012:billing-alarm-topic

Ahora suscribe tu dirección de email al tema. Reemplaza tu-email@ejemplo.com con tu dirección real y el ARN con el que obtuviste en el paso anterior:

aws sns subscribe \
  --topic-arn arn:aws:sns:us-east-1:123456789012:billing-alarm-topic \
  --protocol email \
  --notification-endpoint tu-email@ejemplo.com \
  --region us-east-1

Paso 3: Confirmar la suscripción al email

Revisa tu bandeja de entrada. Recibirás un email de AWS Notifications con un enlace de confirmación. Debes hacer clic en ese enlace antes de continuar — hasta que confirmes, el estado de la suscripción es PendingConfirmation y SNS no entregará alertas a tu email.

Puedes verificar el estado de la suscripción con:

aws sns list-subscriptions-by-topic \
  --topic-arn arn:aws:sns:us-east-1:123456789012:billing-alarm-topic \
  --region us-east-1

Busca que el campo SubscriptionArn muestre un ARN real (no el string PendingConfirmation). Si sigue en pendiente, revisa la carpeta de spam.

Paso 4: Crear la alarma de facturación en CloudWatch

Con el tema SNS confirmado, ya puedes crear la alarma. El parámetro --dimensions con Currency=USD es necesario para filtrar la métrica correctamente — sin él, el comando puede fallar o no encontrar datos.

aws cloudwatch put-metric-alarm \
  --alarm-name 'FreeTier-EstimatedCharges-5USD' \
  --alarm-description 'Alerta cuando los cargos estimados superan 5 USD' \
  --metric-name EstimatedCharges \
  --namespace AWS/Billing \
  --statistic Maximum \
  --period 86400 \
  --evaluation-periods 1 \
  --threshold 5 \
  --comparison-operator GreaterThanOrEqualToThreshold \
  --dimensions Name=Currency,Value=USD \
  --alarm-actions arn:aws:sns:us-east-1:123456789012:billing-alarm-topic \
  --treat-missing-data notBreaching \
  --region us-east-1

Algunos parámetros merecen explicación:

  • --statistic Maximum: La métrica EstimatedCharges es acumulativa durante el mes. Usar Maximum captura el valor más alto del período de evaluación, que es el más representativo del costo real acumulado.
  • --period 86400: Período de 24 horas (en segundos). Dado que la métrica no se actualiza en tiempo real, un período diario es apropiado.
  • --treat-missing-data notBreaching: Evita que la alarma entre en estado ALARM cuando no hay datos disponibles (por ejemplo, al inicio del mes).
  • --threshold 5: El umbral en dólares USD. Ajústalo según tu tolerancia.

Piensa en EstimatedCharges como el odómetro de un coche: solo sube durante el mes, nunca baja hasta que AWS lo reinicia el primer día del mes siguiente. Por eso Maximum es la estadística correcta — quieres el valor más alto registrado, no un promedio que suavice el crecimiento.

Paso 5: Verificar que la alarma de facturación está activa

Una alarma recién creada puede estar en estado INSUFFICIENT_DATA si CloudWatch aún no ha recibido puntos de datos suficientes para evaluarla. Esto es normal durante las primeras horas. Lo que debes confirmar es que la alarma existe y está configurada correctamente, no que ya esté en estado OK.

aws cloudwatch describe-alarms \
  --alarm-names 'FreeTier-EstimatedCharges-5USD' \
  --region us-east-1

En la respuesta, verifica:

  • AlarmName: coincide con el nombre que usaste.
  • Threshold: 5.0
  • AlarmActions: contiene el ARN del tema SNS correcto.
  • Dimensions: muestra Currency: USD.

Si el estado es INSUFFICIENT_DATA después de 24-48 horas, vuelve al Paso 1 y confirma que las métricas de facturación están habilitadas.

Permisos IAM necesarios para configurar la alarma de facturación

Si no estás usando la cuenta raíz — y no deberías estarlo para operaciones cotidianas — el usuario o rol IAM necesita permisos específicos. La política siguiente sigue el principio de mínimo privilegio: CloudWatch con Resource: * (requerido para estas acciones según la Service Authorization Reference) y SNS restringido al ARN del tema específico.

🔽 Ver política IAM mínima requerida
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "CloudWatchBillingAlarm",
      "Effect": "Allow",
      "Action": [
        "cloudwatch:PutMetricAlarm",
        "cloudwatch:DescribeAlarms",
        "cloudwatch:DeleteAlarms"
      ],
      "Resource": "*"
    },
    {
      "Sid": "SNSBillingTopic",
      "Effect": "Allow",
      "Action": [
        "sns:CreateTopic",
        "sns:Subscribe",
        "sns:ListSubscriptionsByTopic"
      ],
      "Resource": "arn:aws:sns:us-east-1:123456789012:billing-alarm-topic"
    }
  ]
}

Nota: el acceso a Billing Preferences para habilitar las métricas de CloudWatch requiere permisos de facturación (aws-portal:ModifyBilling en cuentas antiguas, o permisos del servicio billing en cuentas nuevas). Consulta la documentación de AWS Billing IAM para la versión exacta aplicable a tu cuenta.

Error frecuente: la alarma existe pero nunca se activa

El síntoma es claro: los cargos en la consola de Billing superan $5, pero no llega ningún email. La primera suposición suele ser que la alarma está mal configurada. En la mayoría de los casos, el problema está en otro lugar.

Lo que realmente ocurre: las métricas de facturación nunca se habilitaron, o se habilitaron pero la suscripción SNS sigue en PendingConfirmation. CloudWatch no tiene datos que evaluar, y SNS no tiene a dónde enviar la notificación. La alarma permanece en INSUFFICIENT_DATA silenciosamente.

La corrección tiene dos capas. Primero, verifica que la métrica tiene datos:

aws cloudwatch get-metric-statistics \
  --namespace AWS/Billing \
  --metric-name EstimatedCharges \
  --dimensions Name=Currency,Value=USD \
  --start-time 2024-01-01T00:00:00Z \
  --end-time 2024-01-02T00:00:00Z \
  --period 86400 \
  --statistics Maximum \
  --region us-east-1

Si Datapoints está vacío, las métricas de facturación no están activas. Segundo, verifica el estado de la suscripción SNS con el comando del Paso 3. Ambas capas deben estar operativas para que la alarma funcione de extremo a extremo.

graph TD A["Alarma en INSUFFICIENT_DATA
más de 48 horas"] --> B["¿La métrica tiene datos?
get-metric-statistics"] B -->|"Datapoints vacío"| C["Habilitar métricas
de facturación en Billing Preferences"] B -->|"Datos presentes"| D["¿La alarma transiciona a ALARM?"] D -->|"No transiciona"| E["Revisar threshold
y comparison-operator"] D -->|"Transiciona pero no llega email"| F["Verificar suscripción SNS
list-subscriptions-by-topic"] F --> G{"¿Estado PendingConfirmation?"} G -->|"Sí"| H["Confirmar email
o re-suscribir"] G -->|"No"| I["Revisar filtros de spam
y política del tema SNS"]
  1. Si la alarma está en INSUFFICIENT_DATA por más de 48 horas, el primer punto de verificación es si la métrica tiene datos publicados.
  2. Si la métrica tiene datos pero la alarma no transiciona a ALARM, revisa el umbral y el operador de comparación.
  3. Si la alarma transiciona a ALARM pero no llega email, el problema está en la suscripción SNS — probablemente sigue en PendingConfirmation.

Configurar la alarma de facturación: próximos pasos y recursos

Con la alarma activa, tienes una red de seguridad básica para el Free Tier. Para una cobertura más completa, considera estas extensiones:

  • AWS Budgets: permite alertas más granulares por servicio, región o etiqueta de costo. Complementa las alarmas de CloudWatch con visibilidad de presupuesto.
  • Múltiples umbrales: crea alarmas adicionales a $1 y $10 para tener visibilidad progresiva del gasto.
  • AWS Cost Anomaly Detection: detecta incrementos inusuales en el gasto usando machine learning, sin necesidad de definir umbrales fijos.

Consulta la documentación oficial de CloudWatch para alarmas de facturación y la guía de AWS Budgets para opciones avanzadas de control de costos.

Glosario de términos clave

TérminoDefinición
EstimatedChargesMétrica de CloudWatch en el namespace AWS/Billing que refleja el costo estimado acumulado del mes en curso, en USD. Solo disponible en us-east-1.
SNS TopicCanal de mensajería pub/sub de AWS Simple Notification Service. Actúa como intermediario entre CloudWatch y los suscriptores (email, Lambda, SQS, etc.).
INSUFFICIENT_DATAEstado de una alarma CloudWatch cuando no hay suficientes puntos de datos para evaluarla. No significa que la alarma esté rota, pero sí que no puede tomar decisiones.
Free TierCapa gratuita de AWS que ofrece uso limitado de ciertos servicios durante 12 meses (o de forma permanente para algunos). Superarla genera cargos reales.
treat-missing-dataParámetro de CloudWatch que define cómo tratar los períodos sin datos. notBreaching evita falsas alarmas cuando la métrica no tiene puntos disponibles.

Comentarios

Entradas populares de este blog

EC2 sin acceso a Internet en VPC personalizada: Internet Gateway y Route Table

Actualizar Contenido en CloudFront: Cómo Crear una Invalidación para Limpiar el Caché del Edge

Aumentar el Timeout de Lambda: Configuración, Límites y Diagnóstico en Producción