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

Cases3 cases

1 to 3 of 3

  1. Symptoms

    At about 23:00 UTC on 21 January 2025, an automated alert reported that the CircleCI database instance holding archived data was almost out of free storage space. From 23:50 UTC customers saw slow starts and cancellations of workflows and jobs, and delays and difficulty viewing workflows in the CircleCI UI, although pipelines for a specific project could still be viewed.

    Trigger

    A code change to a function in the archival database on 16 January 2025 unintentionally made it write an excessive number of log messages, and the database filled its storage.

    Root cause
    Component
    Contributing factor
    Detection

    An automated alert at about 23:00 UTC warned that the archival database was almost out of free storage, before customers were affected. The growing workflows queue was not linked to it at first because a separate alert about request volume fired at about the same time.

    Remediation
    • Scaled up the event consumer that processes the workflows queue at 23:44 UTC
    • Promoted a read replica of the archival database to a standalone primary at 23:55 UTC
    Action items
    • Fix the database function so it no longer writes an excessive number of log messages
    • Add a max duration to the workflows retry policy for archiving so it fails earlier than the default timeout
    • Move workflow archival to an event-based model that decouples it from the workflows service
    • Add forecast and anomaly monitoring for databases that alerts on unusual activity before it reaches critical levels
    Lessons

    The storage alert on the archival database did fire, but the database filled much faster than forecast, so there was little time to act before customers were affected. Because the workflows service called the archival service synchronously, a problem in the archival database slowed the whole workflows service.

  2. Symptoms

    Shortly after incident.io moved its infrastructure fully into Google Cloud, the application saw a larger-than-normal number of Postgres connection timeouts, and new database connections per second were in the hundreds, spiking up and down. At the same time, the memcached instance used for transient data and faster API responses had sporadic connection timeouts.

    Trigger

    After the move to Google Cloud, the application opened hundreds of new Postgres connections per second, and an accidental database join made it send thousands of duplicate calls to an external third party in parallel.

    Root cause
    Component
    Contributing factor
    Detection

    An incident was declared when the number of Postgres connection timeouts rose above normal. The remaining cache timeouts were traced through the logs of the Kubernetes node that served an affected request, the request's trace and the node's metrics.

    Remediation
    • Doubled the maximum Postgres connection lifespan from 15m to 30m
    • Made the Postgres connection pools static so they always keep N connections open
    • Raised the memcache client's MaxIdleConns from 2 to 20
    • Moved temporarily from Google's hosted memcached to a memcached inside the Kubernetes cluster
    • Shipped the fix for the accidental database join that made thousands of duplicate external calls
    Action items
    • Set more sensible concurrency limits for outbound network calls
    Lessons

    Network timeouts are not always local to one request or pod: when they appear, the whole activity of the node, including other pods on it, needs to be checked. Staying within a provider's rate limits does not keep outbound calls from affecting a node, so outbound network calls need more sensible concurrency limits.

  3. Symptoms

    On 10 July 2019 the Stripe API failed a substantial majority of requests twice, from 16:35 to 17:02 UTC and from 21:14 to 22:47 UTC. In the first period automated monitoring detected within a minute that a database cluster had failed to elect a new primary.

    Trigger

    The primary node of a database cluster failed at 16:35 UTC while one shard had several stalled nodes. The second period was set off by rolling the election protocol back to the previous minor version at 20:42 UTC.

    Root cause
    Component
    Contributing factor
    Detection

    Automated monitoring detected the failed election within a minute, and the team was alerted at 16:36 UTC. The second period was announced at 21:14 UTC by automated alerts that some shards in the cluster were unavailable.

    Remediation
    • Restarted all nodes of the database cluster, which forced a successful primary election
    • Updated the production configuration and restarted the database cluster's nodes
    • Ramped traffic back up, putting services for user-initiated API requests first
    Action items
    • Alert when nodes stop reporting their replication lag
    • Alert when a shard enters a state that could trigger the election fault
    • Work with the database maintainers on a fix for the underlying fault
    • Add circuit breaking on failed operations to particular database clusters
    • Use fault isolation to contain the impact of a single failed shard
    • Limit the resources used by clients that keep retrying failed requests
    • Add procedures and tooling that make rapid configuration changes during incident response safer
Check your cluster for this

These 3 cases involve Database and In-memory cache. 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