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

Cases4 cases

1 to 4 of 4

  1. Symptoms

    From 20:01 UTC on 28 May 2026, Buildkite build and job notifications (GitHub commit status, email, Slack and webhook notifications) reached a subset of customers late. Internal queue latency monitoring showed the delay as queues grew while notification-processing workers stayed underprovisioned.

    Trigger

    The Prometheus service used by Buildkite's EKS autoscaling path ran out of storage, so some EKS-based notification workers could not autoscale while their queues were growing.

    Root cause
    Component
    Contributing factor
    Detection

    Internal queue latency monitoring detected the rising notification delivery latency.

    Remediation
    • Moved the affected notification-processing workloads from EKS back to the ECS-based infrastructure
    • Adjusted scaling configuration and worker counts by hand
    • Completed the rollback and scaled the remaining affected ECS services
    • Increased Prometheus storage capacity and recorded the change in infrastructure as code
    Action items
    • Alert before Prometheus storage exhaustion can affect autoscaling
    • Fix GitHub notification retry behaviour for a class of errors that could cause repeated retries
    • Make the EKS-to-ECS rollback verify destination capacity, autoscaling configuration and traffic movement
    • Review the CPU, memory and storage allocations of EKS control-plane dependencies such as KEDA and Karpenter
    • Move customer-critical workloads to EKS more gradually, with clearer settling periods
    • Improve customer-level monitoring of notification delivery latency to detect customer-impacting regressions earlier
    • Review which notification types sit on customers' scheduling or CI hot path and need tighter latency, separate queueing or specific alerting
    • Update the status page earlier when notification latency is likely to affect customer workflows
    • Describe the customer-visible impact in status page updates, not only the affected internal service
    • Improve internal escalation for customers who report critical CI impact
    Lessons

    Buildkite said recovery took longer than expected because the rollback path from EKS to ECS did not fully handle this failure, and that its public status page did not show the customer-visible impact as quickly or clearly as it should have, since notification latency affects customers differently depending on how their CI and deployment workflows use notifications.

  2. Symptoms

    On 20 May 2026 a subset of Buildkite customers saw delays in notification delivery, build dispatch and the metrics services. The status page first reported delays to notifications for all customers and later narrowed it to a subset of customers.

    Trigger

    Autoscaling during Buildkite's migration of production services from AWS Fargate to AWS EKS raised the number of pods that Prometheus tracked, and with it the memory the Prometheus server needed.

    Root cause
    Component
    Contributing factor
    Remediation
    • Moved the load of the affected services back to AWS Fargate by following prepared documentation
    • Scaled up the services of a few customers with very large backlogs further by hand
    Action items
    • Upsize the underlying system nodes
    • Set higher requests and limits for the Prometheus server so it can handle more load
    • Review all new EKS resources and set any missing requests and limits
    • Add observability and monitors for EKS pod and node health
  3. Symptoms

    Request latency from the Temporal Server History service, the service that starts workflow executions and records their progress, was higher and less steady than it should be on a self-hosted Kubernetes deployment. The CPU dashboard showed the history pods using less than 60 percent of their CPU, yet the same pods were being throttled.

    Trigger

    Normal load on History pods that had a CPU limit of 2 cores on 8-core nodes, with the Go runtime's GOMAXPROCS left at its default of one per node core.

    Root cause
    Component
    Contributing factor
    Detection

    A Prometheus query for CPU throttling showed the history pods throttled although their CPU usage read under 60 percent.

    Remediation
    • set the GOMAXPROCS environment variable to 2 to match the 2-core CPU limit
    Action items
    • Set GOMAXPROCS automatically from the Kubernetes CPU limit, from Temporal release 1.21.0
    Lessons

    A CPU usage graph averaged over 15 seconds or more can sit far below 100 percent while a container is being throttled, so throttling needs its own metric. A Go program in a container should have GOMAXPROCS matched to its CPU limit, or to its CPU request when it has no limit. The author recommends not using CPU limits at all.

  4. Symptoms

    The NU.nl development team got reports that several services on one of its Kubernetes clusters behaved erratically: occasional error pages, slow responses and timeouts. The affected services were mostly internal tools and dashboards.

    Trigger

    A new ElastAlert rule, deployed shortly before from the command line, that fired if the Cloudfront-* Elasticsearch indexes stopped receiving documents; those indexes take a few million requests per hour, and the rule made ElastAlert's memory grow without bound.

    Root cause
    Component
    Contributing factor
    Detection

    Users reported error pages, slow responses and timeouts from several services; no alert fired.

    Remediation
    • terminated the NotReady nodes one by one so the auto-scaling group replaced them (the new nodes also went NotReady, but Prometheus and Grafana landed on a stable node)
    • found the ElastAlert pods' memory growth on the Grafana pod memory dashboard
    • fixed the ElastAlert problem that caused the memory growth
    Action items
    • Define alerts on resource usage such as CPU, memory and disk space
    • Keep researching an alerting strategy that combines Elasticsearch, Prometheus Alertmanager and New Relic
    • Consider exporting metrics out of the cluster and running Grafana outside it, on EC2 or a separate Kubernetes cluster
    • Either visualise the important metrics in the ELK stack or make Prometheus and Grafana more available, and improve the metrics strategy
    • Set resource limits for ElastAlert through the Helm values
    • Configure namespaces with default memory requests and limits
    • Isolate customer-facing workloads from build, logging and monitoring workloads (a dedicated node group, or later a separate tools cluster)
    • Deploy everything through automation such as Jenkins pipelines, and consider a GitOps approach
    • Deploy through a pipeline that includes a smoke test step
    • Make Kubernetes and cloud infrastructure work part of the team's sprints, picked up by all team members while pairing with more experienced members, and hold workshops that go deep into specific topics
    Lessons

    Fixing the root cause covers only a small part of what an incident can teach; the chain of smaller failures around it is where most of the learning is. A pod without a memory limit can take whole nodes down, so limits need defaults at the namespace level. Monitoring that runs inside the cluster it watches goes blind with it. Changes installed by hand from the command line leave the rest of the team without a record of what changed.

Check your cluster for this

These 4 cases involve Prometheus and Container memory limit. 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