Incident Library
  • Root cause
  • Component
  • Symptom
  • Contributing factor
  • Case

Cases5 cases

1 to 5 of 5

  1. Symptoms

    On 31 March 2026 Buttondown was down twice, for about seven and about thirteen minutes. New requests could not get a database connection and failed, although the database itself was healthy: queries were fast, CPU and memory were fine and replication lag was nominal.

    Root cause
    Component
    Contributing factor
    Detection

    User reports and the team's own manual observation, not automated monitoring. The health check endpoint kept returning 200 for most requests, so no alert fired.

    Remediation
    • Killed active queries to free database connections in the first outage
    • Restarted the database to force-kill the running queries in the second outage
    Action items
    • Reserve a small number of database connections for administrative access
    • Monitor and alert on the database connection count as a percentage of the configured maximum
    • Make the health check endpoint run a lightweight query so connection exhaustion shows in the health checker and the load balancer
    • Add database connection limits to the quarterly capacity review
    • Document and script a fallback that force-recycles workers to release connections without needing a database connection
    Lessons

    Buttondown notes that the tool used to recover from the first outage needed the same resource that was exhausted, which locked the team out during the second outage, and that a health check which cannot detect connection exhaustion, the most common failure mode, gives little protection. A configuration value set long ago drifted out of line with traffic because nobody reviewed it.

  2. Symptoms

    At 17:52 UTC on 12 June 2025, Cloudflare's WARP team saw registrations of new devices failing and declared an incident. Minutes later the Cloudflare Access team got an alert on a rapid rise in error rates, and Service Level Objectives for several other services fell below target. All of them shared one cause: Workers KV was unavailable.

    Trigger

    Part of the storage infrastructure behind Workers KV is backed by a third-party cloud provider, and that provider had an outage. Workers KV could then no longer serve cold reads or writes from its central data store.

    Root cause
    Component
    Contributing factor
    Detection

    The WARP team saw registrations of new devices failing at 17:52 UTC and declared an incident. At 18:05 the Access team received an alert on a rapid increase in error rates and Service Level Objective alerts fired across several teams; at 18:06 the incidents were combined once Workers KV unavailability was identified as the shared cause.

    Remediation
    • Activated the Challenges and Turnstile kill switches so visitors were not blocked
    • Degraded Gateway rules that referenced identity or device posture state to remove the Workers KV dependency
    • Force-dropped Access identity and device posture requests to shed load on Workers KV
    • Worked on a Workers KV release against an alternative backing datastore in case the storage stayed down
    • Restored Access and Device Posture calls to Workers KV once the third-party service was back
    Action items
    • Avoid singular dependencies on storage infrastructure that Cloudflare does not own
    • Improve the ability to recover critical services, including Access, Gateway and WARP
    • Add redundancy to Workers KV's storage infrastructure and remove the dependency on any single provider
    • Make each affected product resilient to the loss of any single point of failure, third-party dependencies included
    • Build tooling to re-enable namespaces progressively during storage incidents, so services come back without overloading Cloudflare's own infrastructure
    Lessons

    Cloudflare holds itself responsible for its choice of dependencies and how it architects around them, even when a vendor failure was the trigger. Building many products on Workers KV normally makes them more robust than separate storage services would, but here the cascading failure of Workers KV made the outage worse and widened its blast radius.

  3. Symptoms

    On 29 July 2019 at 13:14 BST, four minutes after six new servers were added to Monzo's Cassandra cluster at 13:10, automated alerts showed a small percentage of Mastercard card transactions failing, and the tool Customer Operations uses to talk to customers through in-app chat stopped working. Customers could not log in, send or receive payments or withdraw cash, and saw inaccurate balances and transactions.

    Trigger

    At 13:10 BST Monzo added six new servers to its 21-server production Cassandra cluster to add capacity, with auto_bootstrap set to false.

    Root cause
    Component
    Contributing factor
    Detection

    At 13:14 automated alerts reported a small percentage of Mastercard card transactions failing, and Customer Operations reported that its customer communication tool was not working; an incident was declared at 13:15.

    Remediation
    • Deployed a fix for an error-handling bug in a Mastercard service through a planned fallback mechanism, because the deployment tooling was failing
    • Decommissioned the six new Cassandra servers one by one so data ownership returned to the original servers
    • Reconciled the data written while the new servers were serving reads and writes, by replaying externally stored events and running consistency checks
    Action items
    • Fix the use of auto_bootstrap
    • Review and document the decisions behind the other Cassandra settings and write more extensive runbooks for operations such as scale-ups and restarts
    • Expose more Cassandra metrics and consider alerting on strong shifts in metrics such as 'row not found'
    • Split the single Cassandra cluster into several smaller clusters
    Lessons

    Monzo had gaps in its knowledge of rarer Cassandra operations such as adding servers. The scale-up test with one server could not show the problem, because quorum still came from the original replicas, so it did not match adding six servers in production. The lack of metrics pointing at Cassandra delayed the response, and a single shared cluster both let one change have a far-reaching impact and made the failing part harder to find.

  4. Symptoms

    On 22 August 2016 at 17:21 UTC buildkite.com went offline: nobody could log in, view build logs or read the documentation, although builds kept running and GitHub and Bitbucket pull request statuses kept updating. The Buildkite team in Melbourne was asleep and woke at 21:00 UTC, almost 4 hours later, to emails, tweets and Slack messages saying Buildkite was down.

    Trigger

    Over a weekend maintenance window, Buildkite downgraded its m4.10xlarge Multi-AZ RDS PostgreSQL database to an r3.2xlarge Multi-AZ instance to cut its AWS bill, and moved to a centralised pgbouncer to pool connections. The first US weekday peak after the change pushed the new instance's CPU to its maximum at about 16:00 UTC.

    Root cause
    Component
    Contributing factor
    Detection

    New Relic, Pingdom, Datadog, Calibre and CloudWatch raised PagerDuty alerts, but the on-call phone call never came and only silent push notifications arrived. The team noticed at 21:00 UTC when they woke to emails, tweets and Slack messages from users.

    Remediation
    • Moved servers from the Agent API to the dashboard ELB to bring buildkite.com back online
    • Switched the Auto Scaling Groups to EC2 health checks and locked in desired counts
    • Upgraded the database to an instance type that could handle the load, using the aws-cli
    • Built a new AMI that did not depend on buildkite.com/_secret/version and rolled out servers that could self-deploy
    • Removed the centralised pgbouncer and went back to pgbouncer on each host
    Action items
    • Plan load testing after significant infrastructure changes without affecting other users of the system
    • Make the ELB health check return OK when the app answers, without checking database connectivity
    • Consider a separate health check endpoint for Pingdom that checks the database and other dependencies
    • Store the latest deployed revision as a file on S3 for newly launched servers to self-deploy from
    • Test by hand that PagerDuty calls reach every on-call team member
    • Investigate regular company-wide tests of everyone's paging setup
    • Ask PagerDuty about calling members when they go on call or requiring an immediate phone rule
    Lessons

    Buildkite listed six lessons. Watch AWS credits, because billing reports show $0 while credits are spent, so the real cost is hidden and big changes end up rushed. Load test after significant infrastructure changes. Think about what a health check should do and what happens when every server behind an ELB fails it. Do not make new servers look up the deployed revision from the service they are replacing. Make sure every on-call member has the right PagerDuty and phone settings before going on call. When servers churn in AWS, stop health checks and autoscaling, for example with the Auto Scaling feature to suspend and resume processes, so the EC2 request limit is not used up.

  5. Symptoms

    Early on Sunday 20 September 2015, the error rate of customer requests to Amazon DynamoDB in the US-East Region rose far beyond any level of the previous 3 years by 2:37am PDT and settled at about 55%. Some other AWS services in the region that depend on DynamoDB were affected as well.

    Trigger

    At 2:19am PDT a brief network disruption affected a portion of DynamoDB's storage servers, and they all requested their membership data from the metadata service at the same time.

    Root cause
    Component
    Contributing factor
    Detection

    For the errors that remained after the main recovery, a growing number of customer support cases on Monday about tables stuck in the updating or deleting stage and higher than normal error rates showed that the low overall error rate was hitting some customers hard.

    Remediation
    • Paused requests to the metadata service, which cut the retries and relieved its load
    • Added significant capacity to the metadata service once it could answer administrative requests
    • Turned requests to the metadata service back on and returned storage servers to the customer request path
    • Restored a metadata partition that was still not taking its full traffic, ending the remaining errors on Monday
    Action items
    • Significantly increased the capacity of the metadata service, which AWS had already done by the time of the summary
    • Add stricter monitoring on performance dimensions such as membership size, to plan capacity ahead
    • Reduce the rate at which storage nodes request membership data
    • Lengthen the time allowed to process membership queries
    • Segment DynamoDB into many metadata service instances, each serving only part of the storage server fleet
    • Change SQS metadata caching so send and receive keep working without long access to the metadata table
    • Partition work across the Auto Scaling servers to process a backlog of scaling jobs in parallel
    • Prune older scaling activities that have been superseded
    • Increase the capacity available to process scaling activities
    • Change CloudWatch caching of DynamoDB group membership data to refresh only the smallest set of metrics
    • Deliver CloudWatch metrics faster through write-through caching
    • Roll out the shorter timeout on the DynamoDB-dependent API call in Console login
    Lessons

    A low overall error rate can hide disproportionately high error rates for a few customers, and AWS should have posted to the dashboard sooner. A call that does not need to succeed, like the DynamoDB-dependent API call in Console login, should fail quickly instead of blocking on a very long timeout. Splitting the metadata service into many instances, each serving part of the fleet, is meant to contain the impact of software, capacity or infrastructure failures.

Check your cluster for this

These 5 cases involve Database and Cloud load balancer. kubegap audits a Kubernetes cluster for gaps like these, read-only, from Claude Code or Codex; its checks cite public reports like the ones in this library.

By root cause3