Cómo diseñar una pasarela de pagos resiliente con Stripe y Azure

  • Imagen de redactor Daniel J. Saldaña
  • 19 de febrero de 2026
Cómo diseñar una pasarela de pagos resiliente con Stripe y Azure

Integrar pagos parece sencillo hasta que deja de serlo. Mientras todo funciona, un webhook que guarda datos en una base de datos puede parecer suficiente. El problema aparece cuando hay latencia, duplicados, fallos temporales o errores de lógica. En ese momento descubres que procesar dinero no es solo recibir un evento HTTP.

En este artículo quiero explicarte cómo plantear una arquitectura de pagos sólida usando Stripe sobre Microsoft Azure, desplegada como infraestructura como código con Terraform. No vamos a centrarnos en fragmentos de código, sino en las decisiones arquitectónicas que marcan la diferencia entre algo que “funciona” y algo que está preparado para producción real.

Separar responsabilidades desde el primer momento

Cuando Stripe envía un webhook, exige una respuesta rápida. Si no contestas en pocos segundos, reintentará el envío. Eso es parte de su modelo de garantía de entrega.

El error habitual es procesarlo todo dentro del mismo endpoint:

  • Validar firma.
  • Consultar base de datos.
  • Crear o actualizar usuario.
  • Registrar pago.
  • Enviar correos.
  • Devolver respuesta.

Si algo falla en ese flujo —una consulta lenta, un timeout, un problema de red— puedes terminar con estados inconsistentes o duplicados.

La solución es simple conceptualmente, pero potente arquitectónicamente: desacoplar.

La función de entrada debe hacer únicamente esto:

  1. Validar la firma criptográfica.
  2. Publicar el evento en un sistema de eventos.
  3. Devolver 200 inmediatamente.

Nada más.

Event Grid como columna vertebral

En esta arquitectura, Azure Event Grid actúa como intermediario entre el webhook y la lógica de negocio.

Esto cambia completamente el comportamiento del sistema:

  • Si una función falla, Event Grid reintenta automáticamente.
  • Si el fallo persiste, el evento puede enviarse a Dead Letter.
  • Cada tipo de evento puede procesarse en una función distinta.

El sistema deja de depender de un único punto crítico.

Separar eventos como:

  • checkout.session.completed
  • invoice.payment_succeeded
  • customer.subscription.deleted

en funciones independientes permite escalar y evolucionar cada dominio sin romper los demás.

Cosmos DB para el estado

Cosmos DB almacena el estado actual:

  • Usuarios.
  • Suscripciones.
  • Pagos procesados.
  • Identificadores de eventos para idempotencia.

El modo Serverless permite pagar solo por consumo real y escalar automáticamente según tráfico.

Además, su modelo NoSQL se adapta bien a la naturaleza variable de los eventos de Stripe.

Storage Account para auditoría y resiliencia

Una única Storage Account cumple tres funciones importantes:

  1. Table Storage para auditoría ligera.
  2. Blob Storage como Dead Letter.
  3. Queue Storage para errores lógicos.

Si un evento no puede procesarse tras múltiples reintentos, no desaparece. Se almacena en Blob Storage para reprocesarlo cuando el problema esté resuelto.

Si el error es de negocio (por ejemplo, datos inconsistentes), se envía a una cola específica para revisión manual.

Este diseño permite diferenciar entre fallos técnicos y fallos funcionales.

Idempotencia: imprescindible en sistemas de pagos

Stripe puede enviar el mismo evento más de una vez. Esto no es un error, es una característica de fiabilidad.

Por eso, antes de procesar cualquier evento, es obligatorio comprobar si ya fue tratado.

Normalmente se guarda el eventId en Cosmos DB o en una tabla de control. Si ya existe, se ignora. Si no existe, se procesa y se registra.

Sin este control puedes acabar con:

  • Pagos duplicados.
  • Suscripciones dobles.
  • Estados incoherentes.

La idempotencia no es opcional cuando trabajas con dinero.

Seguridad basada en identidad

La seguridad debe basarse en identidad, no en secretos distribuidos por el código.

Cada Azure Function puede tener una Managed Identity asignada. Los permisos se gestionan mediante RBAC:

  • La función de entrada puede publicar en Event Grid.
  • Las funciones de procesamiento pueden acceder a Cosmos DB y Storage.
  • No se usan connection strings en el código.

Además, la validación de la firma de Stripe en el webhook es obligatoria. Si la firma no coincide, se devuelve 401 inmediatamente.

Este enfoque reduce superficie de ataque y simplifica la gestión de credenciales.

Qué ocurre cuando algo falla

Una arquitectura madura define qué pasa cuando el sistema no funciona perfectamente.

  • Si Cosmos DB tiene una caída temporal, Event Grid reintentará automáticamente durante horas.
  • Si hay un bug persistente, el evento terminará en Dead Letter y podrá reprocesarse.
  • Si hay un error de lógica, se enviará a una cola para revisión manual.

Nada se pierde. Todo queda registrado.

Ese es el objetivo real de la arquitectura: garantizar consistencia incluso cuando el entorno falla.

Infraestructura como código

Desplegar todo esto con Terraform aporta ventajas claras:

  • Entornos reproducibles.
  • Versionado de infraestructura.
  • Integración con pipelines de despliegue.
  • Control de cambios auditable.

La infraestructura deja de ser algo manual y pasa a ser parte del ciclo de desarrollo.

Reflexión final

Procesar pagos no es añadir un endpoint HTTP. Es diseñar un sistema distribuido que debe ser consistente, seguro y tolerante a fallos.

Separar entrada y procesamiento, utilizar un backbone de eventos, aplicar idempotencia, implementar seguridad basada en identidad y definir mecanismos claros de recuperación transforma una integración básica en una arquitectura preparada para producción.

La simplicidad inicial puede ser atractiva. Pero cuando el tráfico crece o aparece el primer incidente serio, la arquitectura es lo que marca la diferencia.

¡Suscríbete y recibe actualizaciones sobre tecnología, diseño, productividad, programación y mucho más!
0
0