1 puntos por GN⁺ 2025-11-16 | 1 comentarios | Compartir por WhatsApp
  • Caso en el que se confirmó experimentalmente un bug de condición de carrera ocurrido en AWS Aurora RDS y AWS verificó oficialmente la causa
  • Hightouch detectó, mientras escalaba su sistema de procesamiento de eventos, un fenómeno en el que fallaba el cambio de instancia de escritura durante el proceso de failover de Aurora
  • El análisis de logs mostró que dos instancias realizaban operaciones de escritura al mismo tiempo, lo que provocó conflictos en la capa de almacenamiento y la finalización de procesos
  • AWS confirmó oficialmente que la causa fue que, debido a un problema en el procesamiento de señales internas, el nuevo writer fue promovido antes de que terminara la degradación del writer anterior
  • Este caso resalta la importancia del control de concurrencia en sistemas distribuidos a gran escala y la necesidad de un procedimiento de pausa de escrituras durante un failover

Contexto

  • El 20 de octubre de 2025 ocurrió una interrupción en la región us-east-1 de AWS causada por un bug de condición de carrera en el sistema de gestión de DNS
  • Debido a esto, Hightouch vio un fuerte aumento en el backlog de procesamiento de eventos, hasta llegar al límite del sistema
  • Para asegurar el rendimiento, el 23 de octubre realizó una actualización de instancias de Aurora RDS, y durante ese proceso descubrió un nuevo bug de condición de carrera

Estructura del sistema de eventos de Hightouch

  • El sistema encargado de recopilar y enviar eventos está compuesto por Kubernetes, Kafka y Postgres(Aurora)
  • Postgres se usa como una cola de metadatos por lotes y procesa 500 mil eventos por segundo en menos de 1 segundo
  • Aurora PostgreSQL está compuesto por una instancia solo escritura (primary), una instancia solo lectura (replica) y una capa de almacenamiento compartida

Plan de actualización

  • Agregar una instancia de lectura → actualizar el reader existente y asignarle prioridad de failover → ejecutar el failover → actualizar el writer existente → eliminar el reader temporal
  • Este procedimiento está indicado en la documentación de AWS y había sido validado mediante pruebas de carga en un entorno de staging

Intento de actualización y aparición del problema

  • El 23 de octubre a las 16:39 EDT, después de ejecutar el failover, ocurrió el fenómeno en el que el writer anterior volvía a quedar como primary
  • En ambos intentos ocurrió el mismo resultado, y en algunos servicios aparecieron errores de imposibilidad de escritura: DatabaseError: cannot execute UPDATE in a read-only transaction
  • El análisis de logs confirmó registros donde dos instancias realizaban escrituras al mismo tiempo y terminaban por un conflicto de almacenamiento

Causa de la condición de carrera

  • Durante el proceso de failover de Aurora ocurrió una condición de carrera entre el paso 3 (degradación del writer anterior) y el paso 4 (promoción del nuevo writer)
  • Como resultado, ambas instancias obtuvieron permiso de escritura al mismo tiempo y entraron en conflicto
  • Al reintentar con el tráfico de escritura eliminado, el failover se completó con normalidad, lo que demostró la hipótesis de la condición de carrera

Confirmación y respuesta de AWS

  • Tras una revisión interna, AWS confirmó que la causa fue un error en el procesamiento de la señal de degradación del writer, y que no estaba relacionado con la configuración de Hightouch ni con su patrón de tráfico
  • La corrección está incluida en la hoja de ruta, y como medida temporal AWS recomendó detener las escrituras durante el failover

Medidas finales

  • Hightouch completó la actualización del clúster y además:
    • agregó un procedimiento para detener escrituras antes de un failover intencional
    • reforzó el monitoreo de cambios en el rol de writer
    • actualizó el manual operativo (playbook)

Principales lecciones

  1. Es necesario prepararse para la recuperación ante transiciones de estado inesperadas durante una migración
  2. Contar con observabilidad es clave para detectar el problema
  3. Es importante diseñar para minimizar el impacto entre componentes de un sistema distribuido
  4. Hay que reconocer las diferencias entre el entorno de pruebas y el entorno real de producción

No hay información adicional en el texto original

1 comentarios

 
GN⁺ 2025-11-16
Opiniones en Hacker News
  • Al leer esto, parece que durante un failover manual la aplicación siempre falla si intenta mantener el tráfico de escritura como si nada hubiera pasado.
    Pero deja varias dudas. ¿Por qué otros usuarios de Aurora no se topan siempre con este problema?, ¿cómo podría AWS no saberlo?, y si sí lo sabe, ¿por qué no lo trata como un incidente crítico de nivel P0?
    También da la impresión de que podrían influir condiciones sutiles, como el estado de las transacciones en curso o los timeouts

    • Por mi experiencia manejando problemas parecidos en Azure, mucha gente sí los sufre, pero como se resuelven con un reinicio, los dejan pasar. Encontrar la causa raíz es difícil, y analizarlo junto con el proveedor es tan doloroso que la mayoría termina rindiéndose
    • Nosotros también confirmamos el mismo problema trabajando con AWS. El patrón de tráfico no tenía nada de especial y no se pudo reproducir en otras regiones. Es muy probable que esto sea un defecto fundamental en el mecanismo de failover de Aurora
    • Hace tiempo, con la combinación de Python + MySQL, me topé con un bug donde SELECT ... FOR UPDATE fallaba en silencio y la transacción pasaba a modo autocommit. A nadie le importó y me quedé hablando solo, pero unos meses después otra persona me contactó diciendo que había sufrido exactamente el mismo problema. Al final sí se corrigió, pero para entonces yo ya había perdido el interés
      Enlace relacionado: pregunta en Stack Overflow
    • AWS casi no revela información interna. Como no da detalles más allá del nivel de API, queda la sensación de que estos problemas se descartan como casos raros y se dejan pasar
    • Parte del problema también podría venir de cómo la aplicación reacciona a un failover revertido. Parece que se rompió la caché y siguió intentando escribir en un primario incorrecto. Aunque este tipo de fallo ocurra de vez en cuando, como reintentar suele funcionar, es posible que los usuarios no lo reporten a AWS y por eso AWS ni se entere
  • En Aurora PostgreSQL he visto varias veces comportamientos inesperados.
    En particular, durante Zero Downtime Patching (ZDP), el estado de la sesión se conservó mal y hasta consultas simples terminaban cancelándose mucho antes de statement_timeout.
    Mi sospecha es que, cuando el cliente se reconecta, Aurora hereda el estado de temporizadores viejo de la sesión anterior y por eso la consulta se cancela casi de inmediato

  • Nosotros también hacemos failover de forma regular en un entorno con tráfico de escritura muy alto, pero lo operamos de manera estable con un proceso automatizado usando el AWS JDBC wrapper.

    • En la práctica, la capa de almacenamiento de Aurora evitó una violación de ACID, es decir, la integridad de los datos se mantuvo
  • Uno paga esperando que Aurora mantenga este tipo de invariantes básicos, así que sorprende que ocurra algo así.

    • Aun así, la propia capa de almacenamiento funcionó correctamente al bloquear las escrituras concurrentes
  • Por los logs y la explicación de AWS, parece que la hipótesis del autor original es incorrecta.
    Todo indica que, tras fallar la promoción, un proceso externo de monitoreo detectó una inconsistencia en el estado del clúster y forzó un cierre con kill -9. Los mensajes relacionados con el subsistema de almacenamiento aparecieron después de eso

  • Me gustaría preguntar sobre la comparación de rendimiento entre Aurora y RDS Postgres.
    Si no se necesita Multi-AZ ni failover rápido, ¿RDS con una configuración de gp3 64k IOPS podría dar mejor rendimiento? Aurora da la impresión de tener insert más lento y mayor costo. Además, cuesta confiar en los benchmarks porque muchos ni siquiera aclaran bien la configuración de RDS

    • Nosotros obtuvimos mejor rendimiento y menor costo con Aurora PG 14 en una configuración de 1 writer + 1~2 readers. Aurora conviene porque el almacenamiento se cobra a nivel de clúster y no por instancia.
      Además, no hace falta aprovisionar IOPS manualmente y entrega alrededor de 80k IOPS.
      También hay dos modelos de cobro de IO: pay-per-IO conviene para cargas ligeras, mientras que el modo de tarifa fija favorece workloads con mucho IO.
      Como referencia, Serverless casi siempre fue antieconómico. Solo sirve cuando hay picos cortos de demanda
    • Nuestro equipo sufrió una explosión de costos de I/O en Aurora Postgres RDS. Solo unas pocas fuzzy queries terminaron costando más de $3,000 al mes, cuando originalmente deberían haber sido menos de $100
    • Nos decepcionaron el costo, el rendimiento y la latencia de Aurora, y al final migramos a PostgreSQL on-premises
    • En Aurora MySQL, para igualar el mismo nivel de IOPS en RDS, el costo habría sido muchísimo más alto
    • Aurora no usa EBS y no permite elegir el tipo de almacenamiento ni la latencia. Lo único que se puede elegir es el modelo de cobro de IO
  • Aquí se ve muy bien el “modelo de bloques Lego” del que hablan los ingenieros de AWS.
    Diseñaron la capa de almacenamiento de forma totalmente independiente, así que aunque falle el servicio de arriba, la consistencia de los datos se mantiene. Me parece un buen ejemplo de ingeniería de AWS

  • Dicen que AWS recomendó “detener las escrituras durante el failover”, así que me gustaría saber si podrían compartir el número de caso correspondiente.

    • Nosotros también usamos Aurora MySQL, así que quisiera confirmar si esa recomendación también aplica a MySQL
  • Me da alivio saber que no fui el único que pasó por algo así.

    • AWS Support al principio lo atribuyó a replication lag, pero lo hizo mirando métricas viejas de 24 horas antes. De verdad quisiera saber qué tipo de falla experimentaron y por qué no pudo reproducirse en otras regiones
  • Me parece interesante la arquitectura separada de cómputo y almacenamiento de Aurora.
    Hyperscale de MSSQL tiene una estructura parecida, y es casi el único producto de Azure que personalmente considero realmente utilizable