Cases2 cases
1 to 2 of 2
IL-0268AdGuard DNS resolvers in Amsterdam, Frankfurt and London overloaded and answered with timeouts and SERVFAILAdGuard DNS2025- Symptoms
Between about 15:30 and 18:00 UTC on 25 November 2025 some AdGuard DNS users saw slow or failed DNS resolution, with timeouts and SERVFAIL responses. Alerts fired for increased DNS error rates and server load, and a significant part of the traffic in several European locations, primarily Amsterdam, Frankfurt and London, had intermittent DNS failures for up to 2.5 hours.
- Trigger
A new version of AdGuard DNS, deployed on 25 November to improve how resolvers cache user data, had a bug that saved only the recently changed subset of user data into the local cache file. The first deployment failed partway on a network issue and left about half the servers on the new version; the second attempt made many resolvers start full synchronizations at once.
- Root cause
- Component
- Contributing factor
- Detection
Alerts for increased DNS error rates and server load fired during the second deployment attempt, between 15:30 and 16:00 UTC.
- Remediation
- Rolled back the buggy version on all servers
- Partially rerouted Amsterdam's traffic to other European locations
- Reduced connection concurrency and request pipeline depth in Frankfurt and London, from 5 to 1 in Frankfurt
- Adjusted limits to the actual hardware capacity
- Repaired corrupted cache files and user data snapshots to stop further full synchronizations
- Normalised the traffic distribution once the rollback was complete
- Action items
- Add automated tests that the full user dataset is correctly written to and restored from the local cache file, including detection of empty or truncated caches
- Add integration tests that simulate resolver startup with an empty or corrupted cache under realistic load
- Standardize server hardware profiles per location, or keep separate configurations per hardware class
- Review and adjust connlimit, cache sizes and connection limits for each standard node type
- Reevaluate and lower pipelining depth where needed
- Reevaluate how connections and goroutines are limited so resource use stays bounded with decent throughput after a connection break
- Monitor Go heap size, GC time, GC cycles per second and per-cluster request latency distributions
- Alert on sustained increases in SERVFAIL rate and request duration while upstreams are healthy
- Refine DNS resolver deployment and rollback procedures to avoid simultaneous cache invalidation across a large part of the fleet
- Document and rehearse playbooks for adjusting pipeline depth, connection limits and connlimit during live incidents
- Lessons
How nodes behaved depended on the interaction between available RAM, Go's garbage collector and the connlimit setting. On 64-GiB nodes a high limit let the heap grow large under heavy concurrency and pipelining, and the garbage collector then spent more and more CPU, a known worst case for high-memory applications in which memory is not exhausted but latency rises and throughput falls. On 32-GiB nodes the same configuration reached practical memory limits sooner because it had not been scaled down. Together with high pipelining and client retries, GC pressure, connection saturation and retries formed a feedback loop.
IL-0214PagerDuty's Kafka brokers ran out of JVM heap one after another, and the event APIs rejected events with 502 responsesPagerDuty2025- Symptoms
When a Kafka cluster of PagerDuty's US Service Regions began failing at 03:53 UTC on 28 August 2025, the first alerts pointed to one failing broker. More brokers then ran out of memory, and PagerDuty's event APIs began rejecting incoming events with a response status code of 502 while notifications, webhooks, chat integrations and the REST API degraded.
- Trigger
A new feature that recorded API key usage in a Kafka topic was being rolled out by configuration: 1% on 21 August, 5% and then 25% on 27 August, and 75% on 28 August. A logical error in the feature created a new Kafka producer for every API request instead of reusing one producer.
- Root cause
- Component
- Contributing factor
- Detection
Alerts pointed to one failing Kafka broker at the start of the first incident, and alerts fired again at 16:38 UTC when Kafka performance degraded for the second time. Critical alerts about core API errors were buried among webhook pages.
- Remediation
- Expanded the Kafka cluster and removed the first failing broker
- Doubled the Kafka broker heap size and applied it with a rolling restart across the cluster
- Added status page updates by hand through backup procedures when automated publishing failed
- Recovered Kafka-dependent services, some by manual intervention, and backfilled lost data with scripts
- In the second incident, doubled the heap again with another rolling restart
- Rolled back the API usage feature with a pull request that stopped it from publishing Kafka messages
- Action items
- Remove the dependency that blocked status page automation and simplify and republish the manual runbook
- Run live drills regularly so status updates go out even when parts of the platform are degraded
- Expand JVM and Kafka monitoring of heap, garbage collection and producer and consumer health
- Strengthen service dependency mapping so cascading failures are easier to trace
- Collect customer impact metrics into incident workflows automatically
- Add stricter change management guardrails, with readiness checklists and slower ramp-up windows for major rollouts
- Improve recovery mechanisms in the streaming systems
- Automate communication workflows such as status page updates, internal and external syncs and reminders
- Test major incident workflows monthly with chaos engineering, such as status page failover
- Define clearer incident severity levels and roles, including dedicated communications liaisons
- Lessons
PagerDuty found its message processing more intricate than it had thought: some services had to be restarted to pick up changes, some API activity produced far more messages than expected, and it was hard to tell which parts of the system put heavy load on Kafka. Because producers and JVM heap were barely observed, responders could not see the first failure until several downstream systems were affected, and no one on the call held a model of the whole system. Enabling the feature through configuration rather than a separate deployment was meant as a safety step but made the outage harder to link to the change. Runbooks and backfill scripts were imperfect but gave responders a head start, and the second incident was mitigated in about 50 minutes by repeating the first incident's steps.
These 2 cases involve Language runtime settings and Message broker. 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 cause1
Faulty deployment2 cases
- Contributing factor
- Organisation