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

Cases2 cases

1 to 2 of 2

  1. Symptoms

    From 04:48 UTC on 10 November 2025, queries on the table that stores annotations in Buildkite Pipelines timed out, CPU load on the affected databases rose sharply, and the Agent API, the REST API, GraphQL and the Web UI slowed down and returned more errors.

    Trigger

    At 04:48 UTC a database migration removed an index on the annotations table of the Pipelines product.

    Root cause
    Component
    Contributing factor
    Detection

    At 04:53 UTC the impact of the removed index was detected as queries timing out on the annotations table.

    Remediation
    • Recreated the removed index, finishing on about half of the database shards by 05:30 UTC
    • Temporarily revoked the application user's permission to read from and write to the annotations table
    • Increased max_parallel_maintenance_workers in Postgres to speed up index creation
    • Finished recreating the index on the remaining shards between 07:50 and 08:43 UTC
    • Freed the agents and cleaned up the job states left inconsistent, handling by hand the cases the system could not self-heal, by 11:56 UTC
    Action items
    • Extend the internal tooling that flags risky migrations in code review to cover index removals and ask engineers to verify an index is no longer needed
    • Roll out high-risk migrations to shards in phases instead of to all shards at once
    • Evaluate tools such as HypoPG to analyse index creation and removal
    • Show index usage data from pganalyze more prominently in the development workflow
    • Automate the manual cleanup of inconsistent agent states so the system can heal itself
    Lessons

    Buildkite said the incident was mainly caused by a database migration that exposed gaps in its review process.

  2. 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.

Check your cluster for this

These 2 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 cause2