Incident Library

IL-0310 Hightouch · 2025-10-23databaseaws

An Aurora PostgreSQL failover to an upsized reader reversed twice and backend writes failed in read-only transactions

Hightouch Events uses Amazon Aurora PostgreSQL in us-east-1 as the metadata store for its Postgres-based queues, alongside Kafka and Kubernetes clusters. Aurora separates compute from a shared storage layer replicated across availability zones, and a failover promotes a reader, gives it write access to the storage and points the cluster endpoint at it. After the AWS us-east-1 outage of 20 October 2025 left a large backlog, Hightouch decided to upsize the database on 23 October without a scheduled maintenance window. The plan was to add a temporary reader (instance #3), upsize the existing reader (instance #2) and give it the highest failover priority, fail over to it with an expected downtime under 15s, then upsize the old writer (instance #1) as a reader and remove instance #3. AWS documentation supported the plan, and it had been tested in staging during a load test.

The failovers at 16:39 and 16:43 EDT both reversed. From the database logs Hightouch formed the hypothesis that during the failover window Aurora briefly let both instances process writes, the distributed storage layer rejected the concurrent writes, and both instances crashed: a race between demoting the old writer and accepting writes on the new one. To test this, Hightouch scaled down all services that write to the database, triggered the failover again and watched for storage runtime crashes. Without concurrent writes the failover completed, which strongly reinforced the hypothesis, and the cluster was upsized.

AWS reviewed the findings and confirmed the bug: a signaling problem inside the demotion of the old writer left the writer unchanged after the failover, and nothing in Hightouch's configuration or usage triggered it. AWS said a fix is on its roadmap and, until then, recommends using Aurora failover only as needed and making sure no writes run against the database during a failover.

Severity
–
Scope
Hightouch Events backend services could not run write queries during two failover attempts until they were restarted, and the planned database upsize failed until a controlled failover with all database writers scaled down
Users affected
–
Region
us-east-1
Time to detect
–
Time to resolve
–

Symptoms

At 16:39 EDT on 23 October 2025, Hightouch triggered a failover of its Aurora PostgreSQL cluster in us-east-1 to a newly upsized reader. The AWS Console showed the usual parameter adjustments and instance restarts, but after the page refreshed the original writer was still the primary, and backend services could not run write queries although AWS showed the cluster as healthy.

Backend application logs in some pods showed "DatabaseError: cannot execute UPDATE in a read-only transaction". Database metrics showed a spike in connection count, network traffic and commit throughput on the promoted reader (instance #2) during the failover, while read query traffic from the app did not change, so the extra traffic came from backend services that are meant to reach the writer through the cluster endpoint.

The database logs of both the promoted reader and the original writer showed the same sequence after startup: "LOG: server process (PID 799) was terminated by signal 9: Killed", "DETAIL: Failed process was running: <write query from backend application>", "LOG: terminating any other active server processes", "FATAL: Can't handle storage runtime process crash" and "LOG: database system is shut down".

A second attempt at 16:43 ended the same way, with a brief promotion followed by an immediate reversal. Nothing else had changed: no code updates, no unusual queries and no traffic spikes. The same procedure had passed in a staging environment under load earlier that day, a review of the procedure found no mistake and an online search found no one with the same problem. Restarting the backend services cleared the write errors, but the upgrade had not taken place.

Symptom Failover failureWrites rejected

Root cause

Trigger
A planned upsize of the Aurora cluster's instances, done without a maintenance window, after the AWS us-east-1 outage of 20 October had left an event backlog that strained the small Postgres instance. The manual failover to the upsized reader at 16:39 EDT started the failure.

Detection

The AWS Console showed after a refresh that the original writer was still primary, and backend application logs showed write errors on a read-only transaction. Per-instance query monitoring in Datadog and the RDS database logs showed the brief writer advertisement.

Remediation

Action items

Lessons

Hightouch's takeaways are that a migration can end in the desired state, the starting state or somewhere in between even with services one trusts, so traffic redirection and brief dependency outages should be planned for. The brief writer advertisement could only be found because queries to each instance were monitored in Datadog and the RDS database logs were available. Limiting how much any single component can affect the system helps both uptime and maintenance, and a staging load test, even of the exact procedure, did not reproduce the conditions that triggered the Aurora race condition.

Sources

Related cases

Check your cluster for this

kubegap audits a Kubernetes cluster for conditions like the ones in this case, Database, Database failover manager among them, read-only, from Claude Code or Codex. Its checks cite public reports like this one.

For AI tools and scripts

The API needs no key. The MCP server offers search_incidents, get_incident, list_incidents, get_topic and vocab; both are explained on API and MCP.