<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Prateek Srivastava</title>
    <description>The latest articles on DEV Community by Prateek Srivastava (@prateek_srivastava_6a5661).</description>
    <link>https://dev.to/prateek_srivastava_6a5661</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4086604%2F05a3d228-32cf-48b8-beb4-a0d1b624623b.jpg</url>
      <title>DEV Community: Prateek Srivastava</title>
      <link>https://dev.to/prateek_srivastava_6a5661</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/prateek_srivastava_6a5661"/>
    <language>en</language>
    <item>
      <title>GCP Is Running Out of N2 Machines in us-central1 — And It's Silently Breaking Production Clusters</title>
      <dc:creator>Prateek Srivastava</dc:creator>
      <pubDate>Thu, 27 Aug 2026 17:42:53 +0000</pubDate>
      <link>https://dev.to/prateek_srivastava_6a5661/gcp-is-running-out-of-n2-machines-in-us-central1-and-its-silently-breaking-production-clusters-c0c</link>
      <guid>https://dev.to/prateek_srivastava_6a5661/gcp-is-running-out-of-n2-machines-in-us-central1-and-its-silently-breaking-production-clusters-c0c</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;🔴 &lt;strong&gt;Ongoing&lt;/strong&gt; · Reports active since April 2026 · No official GCP acknowledgement&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Engineers running workloads on Google Cloud Platform's &lt;code&gt;us-central1&lt;/code&gt; region are encountering a growing problem: &lt;strong&gt;GCP cannot provision new n2 VMs on demand&lt;/strong&gt;. The autoscaler requests the machines. GCP says no. Your pods stay &lt;code&gt;Pending&lt;/code&gt;. And the GCP status dashboard sits on green the entire time.&lt;/p&gt;

&lt;p&gt;Google officially defines this error as occurring when &lt;em&gt;"the zone does not have enough resources available to fulfill the request"&lt;/em&gt; — distinguishing it from quota limits, which are a separate class of problem. The error, when you eventually find it buried in GKE cluster-level logs, looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Node scale up in zones us-central1-f associated with this pod failed:
GCE out of resources. Pod is at risk of not being scheduled.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The issue has been documented across Google's own developer forums since &lt;strong&gt;April 2026&lt;/strong&gt;, with fresh reports appearing through August. It has affected n1, n2, and e2 instance types across &lt;em&gt;all&lt;/em&gt; availability zones in us-central1 — zones a, b, c, and f — making the standard "try a different zone" advice ineffective when the shortage is regional.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Engineers Are Reporting on Google's Own Forums
&lt;/h2&gt;

&lt;p&gt;The reports started quietly in spring and have grown louder through summer. These are direct quotes from Google Developer Community discussion threads:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"For many years I've been deploying Compute Engine VMs to us-central-1 region but for the past couple days I've constantly received error ZONE_RESOURCE_POOL_EXHAUSTED."&lt;/em&gt;&lt;br&gt;
— Kevin_Koehler, April 13, 2026 · Google Developer Community&lt;/p&gt;

&lt;p&gt;&lt;em&gt;"Assumed it was a temporary resource shortage but it's been happening consistently for the past week, which has been very frustrating."&lt;/em&gt;&lt;br&gt;
— nju, May 18, 2026 · Google Developer Community&lt;/p&gt;

&lt;p&gt;&lt;em&gt;"I tried zones a, b, c, and f. Same issue. I tried e2, n1, n2. Same issue... I guess GCP doesn't want my money anymore 🤷"&lt;/em&gt;&lt;br&gt;
— standev, August 13, 2026 · Google Developer Community&lt;/p&gt;

&lt;p&gt;⚠️ &lt;strong&gt;No Official Response.&lt;/strong&gt; As of the time of writing, no Google employee has responded to these forum threads, and no incident has been posted to the GCP Status Dashboard for this issue. The gap between what users experience and what Google publicly acknowledges is the defining characteristic of this problem.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The Failure Mode That Looks Like Slowness
&lt;/h2&gt;

&lt;p&gt;What makes this particularly dangerous for production systems is how the failure presents itself. When GCP cannot provision a requested machine type, it does not return an error to your application. The GKE cluster autoscaler keeps retrying silently. Your worker pods stay in &lt;code&gt;Pending&lt;/code&gt; state. Your job scheduler marks tasks as still running. Your monitoring dashboards show activity. Nothing appears broken.&lt;/p&gt;

&lt;p&gt;The only place the truth surfaces is in GKE cluster-level logs — not in your application logs, not in your job scheduler UI. Most engineers only look there when something is visibly broken, which by then is hours later.&lt;/p&gt;

&lt;p&gt;In distributed batch workloads on GKE, a common pattern is a lightweight &lt;strong&gt;driver pod&lt;/strong&gt; that coordinates the job and schedules work across &lt;strong&gt;executor (worker) pods&lt;/strong&gt; that do the actual computation. When this capacity issue strikes, the driver pod starts successfully — it's small and fits on an existing node. The executor pods, which need the new n2 VMs the autoscaler is trying to provision, never arrive. From the outside, the job appears to be running. Internally, it's doing nothing.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Time&lt;/th&gt;
&lt;th&gt;What Happens&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;T + 0 min&lt;/td&gt;
&lt;td&gt;Driver pod created, job shows as RUNNING. Everything looks normal.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;T + ongoing&lt;/td&gt;
&lt;td&gt;Autoscaler requests new n2 nodes — GCP cannot fulfil. Worker pods remain Pending. No error surfaced to the app layer.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;T + hours later&lt;/td&gt;
&lt;td&gt;GCP eventually finds capacity — workers schedule, job completes. Having waited hours to do minutes of work.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"The driver node got created around 19:30 UTC but the executors were allocated only around 00:30 UTC — 5 hours later. This is the case with all the tasks."&lt;/em&gt;&lt;br&gt;
— Platform engineer's documented incident report&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Google's own GKE documentation acknowledges this scenario, stating the resolution is to &lt;em&gt;"try a different zone, or try again later."&lt;/em&gt; When the shortage is regional and persistent — spanning all zones for hours — neither of those options helps in the moment.&lt;/p&gt;

&lt;h2&gt;
  
  
  Which Machine Types Are Affected
&lt;/h2&gt;

&lt;p&gt;Based on community forum reports, the issue is not limited to a single machine family:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Machine Family&lt;/th&gt;
&lt;th&gt;Types Reported&lt;/th&gt;
&lt;th&gt;Zones (us-central1)&lt;/th&gt;
&lt;th&gt;Community Status&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;n2&lt;/td&gt;
&lt;td&gt;n2-standard, n2-highmem (all sizes)&lt;/td&gt;
&lt;td&gt;a, b, c, f&lt;/td&gt;
&lt;td&gt;❌ Most frequently reported&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;n1&lt;/td&gt;
&lt;td&gt;n1-standard, n1-highmem&lt;/td&gt;
&lt;td&gt;a, b, c, f&lt;/td&gt;
&lt;td&gt;❌ Also reported&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;e2&lt;/td&gt;
&lt;td&gt;e2-medium, e2-standard&lt;/td&gt;
&lt;td&gt;Some zones&lt;/td&gt;
&lt;td&gt;⚠️ Intermittent reports&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;n2d&lt;/td&gt;
&lt;td&gt;n2d-highmem, n2d-standard&lt;/td&gt;
&lt;td&gt;a, b, c, f&lt;/td&gt;
&lt;td&gt;⚠️ Some teams found better availability&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;c4&lt;/td&gt;
&lt;td&gt;c4-highmem, c4-standard&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;✅ No shortage reports found (Aug 2026)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Three Actions You Can Take Today
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Stop autoscaling from zero on SLA-critical node pools
&lt;/h3&gt;

&lt;p&gt;When your minimum node count is zero, a capacity crunch becomes an indefinite stall — the autoscaler cannot get new nodes, and no existing nodes are available either. Raising the minimum floor means your workloads always have somewhere to land.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Before — zero floor, entirely dependent on autoscaler from scratch&lt;/span&gt;
&lt;span class="nx"&gt;min_node_count&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="nx"&gt;max_node_count&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;

&lt;span class="c1"&gt;# After — warm baseline; autoscaler supplements from here&lt;/span&gt;
&lt;span class="nx"&gt;min_node_count&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;
&lt;span class="nx"&gt;max_node_count&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Always commit this change through your IaC tooling (Terraform / Terragrunt). A manual GCP Console change is not reflected in state and will be silently overwritten on the next &lt;code&gt;apply&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Try a different machine type
&lt;/h3&gt;

&lt;p&gt;Google's official troubleshooting documentation explicitly lists &lt;em&gt;"selecting a different machine series or type"&lt;/em&gt; as a recommended workaround for &lt;code&gt;ZONE_RESOURCE_POOL_EXHAUSTED&lt;/code&gt;. Some teams have had better provisioning success with &lt;code&gt;n2d&lt;/code&gt; compared to &lt;code&gt;n2&lt;/code&gt; during this period.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gcloud beta container node-pools update YOUR-NODEPOOL-NAME &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--project&lt;/span&gt;      YOUR-PROJECT-ID &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--cluster&lt;/span&gt;      YOUR-CLUSTER-NAME &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--region&lt;/span&gt;       us-central1 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--machine-type&lt;/span&gt; n2d-highmem-16
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Plan for approximately 30 minutes of node pool downtime. Schedule this during a quiet window and validate the new machine type on a non-production cluster first.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Alert on pod pending time — not just job failure
&lt;/h3&gt;

&lt;p&gt;This failure mode presents as slowness, not an error. Your job scheduler will not raise an alert — it sees the job as running. Set a Kubernetes-level alert on pod pending duration.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# List all Pending pods across namespaces&lt;/span&gt;
kubectl get pods &lt;span class="nt"&gt;-A&lt;/span&gt; &lt;span class="nt"&gt;--field-selector&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;status.phase&lt;span class="o"&gt;=&lt;/span&gt;Pending

&lt;span class="c"&gt;# Inspect a specific pod — look in Events for the root cause&lt;/span&gt;
kubectl describe pod &amp;lt;pod-name&amp;gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &amp;lt;namespace&amp;gt;
&lt;span class="c"&gt;# GCE out of resources  →  capacity problem (this article)&lt;/span&gt;
&lt;span class="c"&gt;# Insufficient cpu/memory  →  resource request too large for available nodes&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Long-Term Answer: Consider Migrating to C4
&lt;/h2&gt;

&lt;p&gt;The C4 machine series — powered by Intel Emerald Rapids processors and Google's Titanium offload chips — is Google's current-generation compute offering, and no documented community reports of &lt;code&gt;ZONE_RESOURCE_POOL_EXHAUSTED&lt;/code&gt; for C4 have been found as of August 2026.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Spec&lt;/th&gt;
&lt;th&gt;n2-highmem&lt;/th&gt;
&lt;th&gt;c4-highmem&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Processor&lt;/td&gt;
&lt;td&gt;Intel Cascade Lake / Ice Lake&lt;/td&gt;
&lt;td&gt;Intel Emerald Rapids (5th Gen Xeon)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Max vCPUs&lt;/td&gt;
&lt;td&gt;128&lt;/td&gt;
&lt;td&gt;192&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Max memory&lt;/td&gt;
&lt;td&gt;864 GB&lt;/td&gt;
&lt;td&gt;1.5 TB DDR5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Network bandwidth&lt;/td&gt;
&lt;td&gt;Up to 100 Gbps&lt;/td&gt;
&lt;td&gt;Up to 200 Gbps&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Price-performance&lt;/td&gt;
&lt;td&gt;Baseline&lt;/td&gt;
&lt;td&gt;Up to 25% better vs C3&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 &lt;strong&gt;Migration approach:&lt;/strong&gt; The safest path is to create a new C4 node pool alongside your existing n2 pool, validate your workloads on the new pool, then drain and delete the old one. This avoids any single-pool downtime and lets you roll back cleanly if something doesn't behave as expected.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Before migrating, validate on a pre-production cluster first. C4 uses Hyperdisk as its storage backend by default rather than standard persistent disks — confirm compatibility before rolling to production.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. The GCP status page is not your monitoring.&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;ZONE_RESOURCE_POOL_EXHAUSTED&lt;/code&gt; does not appear as a GCP incident. Monitor your cluster directly — pod pending duration is a more reliable early-warning signal than any external status page.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Minimum node count zero is a risk for production batch.&lt;/strong&gt;&lt;br&gt;
Autoscaling from zero is cost-efficient under normal conditions. Under capacity constraints it means indefinite waits. For jobs with SLAs, maintain a warm baseline.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Multi-zone helps — regional shortages need a different response.&lt;/strong&gt;&lt;br&gt;
Zone diversity protects against single-zone hardware failures. When the shortage is regional, the only effective responses are machine type diversity or capacity reservations made in advance.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Know your machine type fallback before you need it.&lt;/strong&gt;&lt;br&gt;
Google explicitly recommends switching machine series as a workaround. Have a tested alternative machine type ready in your runbook — the wrong time to figure it out is during a production incident at 3 AM.&lt;/p&gt;




&lt;p&gt;The frustrating reality of &lt;code&gt;ZONE_RESOURCE_POOL_EXHAUSTED&lt;/code&gt; is that it sits in a grey zone: widespread enough to affect multiple teams across months, specific enough that Google doesn't surface it as a regional incident. The community has been documenting it since April. The status page has stayed green throughout.&lt;/p&gt;

&lt;p&gt;If you're running SLA-critical workloads in us-central1 on n2 — especially with a minimum node count of zero — the fixes above are worth reviewing this week, not after the next unexplained multi-hour delay.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sources
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://discuss.google.dev/t/sudden-vm-unavailability-in-us-central-1/349095" rel="noopener noreferrer"&gt;Sudden VM Unavailability in us-central-1 (Apr–Aug 2026) — Google Developer Community&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://discuss.google.dev/t/shortage-of-compute-engine-resource-in-us-central-1/97319" rel="noopener noreferrer"&gt;Shortage of Compute Engine Resource in us-central-1 — Google Developer Forums&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.cloud.google.com/compute/docs/troubleshooting/troubleshooting-resource-availability" rel="noopener noreferrer"&gt;Troubleshooting Resource Availability Errors — Google Cloud Docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://cloud.google.com/blog/products/compute/a-closer-look-at-compute-engine-c4-and-n4-machine-series/" rel="noopener noreferrer"&gt;C4 and N4 Machine Series Deep Dive — Google Cloud Blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.cloud.google.com/kubernetes-engine/docs/troubleshooting/troubleshoot-node-pools" rel="noopener noreferrer"&gt;Troubleshoot GKE Standard Node Pools — Google Cloud Docs&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;If you’re dealing with something like this at work — or you have a war story of your own — I’m on &lt;a href="https://www.linkedin.com/in/prateeksrivastava123/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; and I actually respond.&lt;br&gt;
I publish one production incident breakdown every week. Subscribe free if you want it directly in your inbox — no tutorials, no fluff:&lt;br&gt;
Let’s Stay in Touch 🪂 Connect with me on: &lt;a href="https://www.linkedin.com/in/prateeksrivastava123/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;, &lt;a href="https://www.instagram.com/prateek1088/" rel="noopener noreferrer"&gt;Instagram&lt;/a&gt;, &lt;a href="https://medium.com/@prateeksrivastav598" rel="noopener noreferrer"&gt;Medium&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>gcp</category>
      <category>kubernetes</category>
      <category>devops</category>
      <category>sre</category>
    </item>
    <item>
      <title>Claude Went Down Today. And It Says More About AI Than You Might Think !!!!</title>
      <dc:creator>Prateek Srivastava</dc:creator>
      <pubDate>Mon, 24 Aug 2026 08:58:45 +0000</pubDate>
      <link>https://dev.to/prateek_srivastava_6a5661/claude-went-down-today-and-it-says-more-about-ai-than-you-might-think--19ec</link>
      <guid>https://dev.to/prateek_srivastava_6a5661/claude-went-down-today-and-it-says-more-about-ai-than-you-might-think--19ec</guid>
      <description>&lt;h1&gt;
  
  
  Claude Went Down Today — And It Says More About AI Than You Might Think
&lt;/h1&gt;

&lt;p&gt;If you tried using &lt;strong&gt;Claude today&lt;/strong&gt; and suddenly started seeing errors, failed requests, or responses that wouldn't complete, you weren't alone.&lt;/p&gt;

&lt;p&gt;On &lt;strong&gt;August 24, 2026&lt;/strong&gt;, Anthropic experienced a service disruption affecting multiple Claude models and services. Anthropic reported elevated errors and said it had identified the cause and was working on a fix.&lt;/p&gt;

&lt;p&gt;At the time of writing, the situation has improved and Anthropic's status page shows its services as operational.&lt;/p&gt;

&lt;p&gt;But the interesting part isn't simply that &lt;strong&gt;Claude went down&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The interesting part is &lt;strong&gt;how much this kind of outage matters now.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A few years ago, an AI chatbot going offline would have been an inconvenience.&lt;/p&gt;

&lt;p&gt;Today, it can interrupt software development, automation, research, content creation, and entire business workflows.&lt;/p&gt;

&lt;p&gt;And developers should pay attention to that.&lt;/p&gt;




&lt;h2&gt;
  
  
  Claude Isn't Just a Chatbot Anymore
&lt;/h2&gt;

&lt;p&gt;This is probably the biggest change.&lt;/p&gt;

&lt;p&gt;People don't use Claude only to ask questions anymore.&lt;/p&gt;

&lt;p&gt;Developers use Claude to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Write and review code&lt;/li&gt;
&lt;li&gt;Debug applications&lt;/li&gt;
&lt;li&gt;Refactor large codebases&lt;/li&gt;
&lt;li&gt;Generate tests&lt;/li&gt;
&lt;li&gt;Analyze repositories&lt;/li&gt;
&lt;li&gt;Work with Claude Code&lt;/li&gt;
&lt;li&gt;Process documents&lt;/li&gt;
&lt;li&gt;Automate repetitive tasks&lt;/li&gt;
&lt;li&gt;Build applications through the Claude API&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For many developers, &lt;strong&gt;Claude has become part of the development environment.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;So when Claude becomes unavailable, the problem isn't necessarily:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"My AI chatbot isn't working."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It can be:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Part of my development workflow just stopped."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That's a very different situation.&lt;/p&gt;




&lt;h2&gt;
  
  
  AI Is Quietly Becoming Infrastructure
&lt;/h2&gt;

&lt;p&gt;We often compare AI models based on intelligence.&lt;/p&gt;

&lt;p&gt;Which model is better at coding?&lt;/p&gt;

&lt;p&gt;Which one reasons better?&lt;/p&gt;

&lt;p&gt;Which one produces better results?&lt;/p&gt;

&lt;p&gt;Which one wins the latest benchmark?&lt;/p&gt;

&lt;p&gt;Those comparisons are useful, but there's another question that becomes increasingly important as we use AI in production:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can I depend on this service being available when I need it?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That's an infrastructure question.&lt;/p&gt;

&lt;p&gt;And AI providers are increasingly becoming infrastructure providers.&lt;/p&gt;

&lt;p&gt;If your application depends on Claude's API, then Claude's availability becomes part of your application's availability.&lt;/p&gt;

&lt;p&gt;That's something developers shouldn't ignore.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Single-Provider Problem
&lt;/h2&gt;

&lt;p&gt;Imagine building an application where every important AI operation goes through one provider.&lt;/p&gt;

&lt;p&gt;Everything works perfectly.&lt;/p&gt;

&lt;p&gt;Until it doesn't.&lt;/p&gt;

&lt;p&gt;Your code may be perfectly written.&lt;/p&gt;

&lt;p&gt;Your infrastructure may be healthy.&lt;/p&gt;

&lt;p&gt;Your database may be online.&lt;/p&gt;

&lt;p&gt;Your users may have a working internet connection.&lt;/p&gt;

&lt;p&gt;But if your AI provider is unavailable, a critical feature can still fail.&lt;/p&gt;

&lt;p&gt;That's the downside of tightly coupling an application to a single AI provider.&lt;/p&gt;

&lt;p&gt;It doesn't mean you should avoid Claude.&lt;/p&gt;

&lt;p&gt;It means you should &lt;strong&gt;design your system with failure in mind.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  What Happens When Claude Goes Down?
&lt;/h2&gt;

&lt;p&gt;This is the question every developer building an AI-powered application should ask.&lt;/p&gt;

&lt;p&gt;Not:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"What if the model gives a bad answer?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"What if I can't reach the model at all?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;These are very different failure modes.&lt;/p&gt;

&lt;p&gt;A bad response can potentially be validated, rejected, or corrected.&lt;/p&gt;

&lt;p&gt;An unavailable API gives you nothing.&lt;/p&gt;

&lt;p&gt;Your application needs to know how to handle that.&lt;/p&gt;

&lt;p&gt;For example, a basic architecture might look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User Request
     ↓
AI Service
     ↓
Claude API
     ↓
Success
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's simple.&lt;/p&gt;

&lt;p&gt;But a more resilient architecture might look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User Request
     ↓
AI Gateway
     ↓
Claude
     ↓
If unavailable
     ↓
Fallback Model
     ↓
If unavailable
     ↓
Cached / Degraded Response
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You don't necessarily need a complicated architecture for every project.&lt;/p&gt;

&lt;p&gt;But for production systems, the principle is important:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Don't make one AI provider a single point of failure.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Fallbacks Are Becoming Important
&lt;/h2&gt;

&lt;p&gt;One of the easiest improvements is having a &lt;strong&gt;fallback model&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For example, your application might use Claude as the primary model.&lt;/p&gt;

&lt;p&gt;If requests start failing, your system can route certain requests to another model.&lt;/p&gt;

&lt;p&gt;The fallback doesn't have to be identical.&lt;/p&gt;

&lt;p&gt;Maybe the primary model handles complex reasoning while the fallback handles simpler requests.&lt;/p&gt;

&lt;p&gt;Maybe one provider handles coding while another handles classification or summarization.&lt;/p&gt;

&lt;p&gt;The exact architecture depends on the application.&lt;/p&gt;

&lt;p&gt;The important thing is &lt;strong&gt;having a plan&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Retries Aren't Enough
&lt;/h2&gt;

&lt;p&gt;A common response to API failures is simply:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Request failed
→ retry
→ retry
→ retry
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's not always a good strategy.&lt;/p&gt;

&lt;p&gt;During a real outage, thousands of applications may already be retrying requests.&lt;/p&gt;

&lt;p&gt;If every application aggressively retries, the additional traffic can make the situation worse.&lt;/p&gt;

&lt;p&gt;Instead, use:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Exponential backoff&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Reasonable retry limits&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Timeouts&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Circuit breakers&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Rate-limit handling&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Idempotency where appropriate&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Your application should be able to recognize:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;"The provider is having trouble. Stop hammering it."&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Graceful Degradation Matters Too
&lt;/h2&gt;

&lt;p&gt;Not every AI feature needs to bring down the entire application.&lt;/p&gt;

&lt;p&gt;Suppose your application uses AI to generate summaries.&lt;/p&gt;

&lt;p&gt;If the AI provider is unavailable, perhaps users can still:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Upload documents&lt;/li&gt;
&lt;li&gt;Browse existing summaries&lt;/li&gt;
&lt;li&gt;Save their work&lt;/li&gt;
&lt;li&gt;Queue the request&lt;/li&gt;
&lt;li&gt;Try again later&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The application doesn't need to become completely useless.&lt;/p&gt;

&lt;p&gt;This is what &lt;strong&gt;graceful degradation&lt;/strong&gt; looks like.&lt;/p&gt;

&lt;p&gt;The AI feature can fail while the rest of the product continues working.&lt;/p&gt;

&lt;p&gt;That's much better than:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AI API unavailable
        ↓
500 Internal Server Error
        ↓
Everything is broken
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Monitoring Shouldn't Start After an Outage
&lt;/h2&gt;

&lt;p&gt;Another lesson from incidents like this is &lt;strong&gt;monitoring&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If you're building with an AI API, don't only monitor whether your own server is healthy.&lt;/p&gt;

&lt;p&gt;Monitor the AI dependency too.&lt;/p&gt;

&lt;p&gt;At minimum, keep an eye on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Request success rate&lt;/li&gt;
&lt;li&gt;Error rate&lt;/li&gt;
&lt;li&gt;Latency&lt;/li&gt;
&lt;li&gt;Timeouts&lt;/li&gt;
&lt;li&gt;Rate limits&lt;/li&gt;
&lt;li&gt;Token usage&lt;/li&gt;
&lt;li&gt;Provider availability&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And ideally, your system should distinguish between:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;My application is broken
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;My AI provider is having an incident
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Those are completely different problems.&lt;/p&gt;




&lt;h2&gt;
  
  
  Claude Code Makes This Even More Interesting
&lt;/h2&gt;

&lt;p&gt;The impact of Claude outages is particularly interesting for developers because of &lt;strong&gt;Claude Code&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;AI coding tools have changed the developer workflow.&lt;/p&gt;

&lt;p&gt;Instead of asking an AI to complete one line of code, developers can increasingly give an agent a larger task:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Understand this repository.
Find the problem.
Modify the relevant files.
Run the tests.
Fix any failures.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's a much deeper integration with the development process.&lt;/p&gt;

&lt;p&gt;When that tool becomes unavailable, the impact isn't simply losing a chatbot.&lt;/p&gt;

&lt;p&gt;It's losing &lt;strong&gt;part of your development workflow.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;And that's exactly why reliability is becoming so important.&lt;/p&gt;




&lt;h2&gt;
  
  
  The "Best Model" Isn't Always the Best Choice
&lt;/h2&gt;

&lt;p&gt;Here's another thought.&lt;/p&gt;

&lt;p&gt;Suppose &lt;strong&gt;Model A&lt;/strong&gt; is slightly better than &lt;strong&gt;Model B&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;But Model A is your only provider.&lt;/p&gt;

&lt;p&gt;Model B is slightly less capable, but your system can automatically fail over to it.&lt;/p&gt;

&lt;p&gt;For a production application, Model B might actually provide a better overall user experience.&lt;/p&gt;

&lt;p&gt;Because users don't care about benchmark scores when your application is returning errors.&lt;/p&gt;

&lt;p&gt;They care whether the product works.&lt;/p&gt;

&lt;p&gt;That's why the future of AI engineering probably isn't going to be about picking one model and sticking with it forever.&lt;/p&gt;

&lt;p&gt;It's going to be about &lt;strong&gt;model orchestration and resilience.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  AI Reliability Is Becoming a Feature
&lt;/h2&gt;

&lt;p&gt;We've traditionally thought about AI companies competing on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Model intelligence&lt;/li&gt;
&lt;li&gt;Context windows&lt;/li&gt;
&lt;li&gt;Reasoning&lt;/li&gt;
&lt;li&gt;Coding ability&lt;/li&gt;
&lt;li&gt;Multimodal capabilities&lt;/li&gt;
&lt;li&gt;Cost&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Increasingly, we'll also care about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Uptime&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Latency&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;API stability&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Rate limits&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Incident response&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Observability&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Developer experience&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's actually a sign of progress.&lt;/p&gt;

&lt;p&gt;When people start caring about uptime, it means the technology has become important enough to depend on.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Developers Can Do Today
&lt;/h2&gt;

&lt;p&gt;If you're building an application around Claude or any other AI provider, today's incident is a good excuse to review your architecture.&lt;/p&gt;

&lt;p&gt;Ask yourself:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. What happens if the API returns 500 errors?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. What happens if requests start timing out?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. What happens if the provider is unavailable for an hour?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Do I have a fallback model?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Can users continue using the non-AI parts of my application?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. Do I have monitoring and alerts?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;7. Am I retrying intelligently?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;8. Can important AI results be cached or queued?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you don't have good answers yet, that's okay.&lt;/p&gt;

&lt;p&gt;But it's worth thinking about &lt;strong&gt;before the next outage rather than during it.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The Bigger Lesson
&lt;/h2&gt;

&lt;p&gt;I'm not particularly interested in using today's incident to argue that Claude is bad.&lt;/p&gt;

&lt;p&gt;Every major technology platform will eventually have outages.&lt;/p&gt;

&lt;p&gt;The more interesting lesson is what the outage reveals about the industry.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AI has moved beyond being a novelty.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It's becoming infrastructure.&lt;/p&gt;

&lt;p&gt;Developers are building applications on top of these models.&lt;/p&gt;

&lt;p&gt;Companies are integrating them into internal workflows.&lt;/p&gt;

&lt;p&gt;People are using them to write software.&lt;/p&gt;

&lt;p&gt;And once something becomes infrastructure, &lt;strong&gt;reliability matters just as much as capability.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That's the real story behind today's Claude outage.&lt;/p&gt;

&lt;p&gt;Not that an AI service stopped working for a while.&lt;/p&gt;

&lt;p&gt;But that we've reached a point where &lt;strong&gt;an AI service going offline can stop real work from happening.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;And if you're building with AI today, that's something worth designing for.&lt;/p&gt;




&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;The next time someone asks:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;"Which AI model should I use?"&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Maybe the answer shouldn't only be about benchmarks, coding performance, or reasoning ability.&lt;/p&gt;

&lt;p&gt;Ask another question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;"What happens when that model goes down?"&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Because eventually, it will.&lt;/p&gt;

&lt;p&gt;And the applications that survive won't necessarily be the ones using the smartest model.&lt;/p&gt;

&lt;p&gt;They'll be the ones designed to &lt;strong&gt;keep working when the smartest model isn't available.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Sources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Anthropic Claude Status&lt;/strong&gt; — Official service status and incident history:&lt;br&gt;
&lt;a href="https://status.claude.com/" rel="noopener noreferrer"&gt;https://status.claude.com/&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Notebookcheck&lt;/strong&gt; — Coverage of the Claude outage and elevated errors affecting multiple models:&lt;br&gt;
&lt;a href="https://www.notebookcheck.net/Claude-faces-another-outage-as-errors-hit-multiple-models.1376666.0.html" rel="noopener noreferrer"&gt;https://www.notebookcheck.net/Claude-faces-another-outage-as-errors-hit-multiple-models.1376666.0.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Android Authority&lt;/strong&gt; — Coverage of the August 24 Claude disruption:&lt;br&gt;
&lt;a href="https://www.androidauthority.com/claude-outage-august-24-3702012/" rel="noopener noreferrer"&gt;https://www.androidauthority.com/claude-outage-august-24-3702012/&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Economic Times&lt;/strong&gt; — Coverage of user reports and the Claude service disruption:&lt;br&gt;
&lt;a href="https://m.economictimes.com/news/new-updates/claude-down-today-users-report-issues-as-downdetector-shows-big-spike-heres-latest-update/articleshow/133456017.cms" rel="noopener noreferrer"&gt;https://m.economictimes.com/news/new-updates/claude-down-today-users-report-issues-as-downdetector-shows-big-spike-heres-latest-update/articleshow/133456017.cms&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  What do you think?
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Has your development workflow become too dependent on AI providers?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I'd be interested to hear how you're handling AI outages — fallback models, queues, caching, or simply switching back to writing code manually.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>webdev</category>
      <category>productivity</category>
    </item>
    <item>
      <title>A Windows Service is Down. Now What?</title>
      <dc:creator>Prateek Srivastava</dc:creator>
      <pubDate>Sun, 23 Aug 2026 19:29:55 +0000</pubDate>
      <link>https://dev.to/prateek_srivastava_6a5661/a-windows-service-is-down-now-what-2gh9</link>
      <guid>https://dev.to/prateek_srivastava_6a5661/a-windows-service-is-down-now-what-2gh9</guid>
      <description>&lt;p&gt;It doesn't matter if it's SQL Server, IIS, a background agent, or a custom app — when a Windows service goes down, the investigation is always the same five moves. Learn the pattern once, apply it to anything.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;🚫 &lt;strong&gt;Don't restart first.&lt;/strong&gt; Restarting a service without knowing why it stopped can hide a real problem — a failing update, an exhausted host, or an automation script that will stop it again in the next cycle. Spend 5 minutes on the evidence first.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Step 01 — Confirm Current State
&lt;/h2&gt;

&lt;p&gt;Your first question isn't "why did it stop?" — it's "is it still stopped?" Monitoring systems have polling intervals; by the time an alert reaches you, the service may have already recovered. Establish ground truth before taking any action.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;Get-Service&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ServiceName1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ServiceName2"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;Select-Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;StartType&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two things matter: &lt;strong&gt;Status&lt;/strong&gt; (is it actually down right now?) and &lt;strong&gt;StartType&lt;/strong&gt; (is it still set to Automatic? OS updates occasionally reset this).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;🔵 &lt;strong&gt;SQL Server example:&lt;/strong&gt;&lt;/p&gt;


&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;Get-Service&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;MSSQLSERVER&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;SQLSERVERAGENT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;MsDtsServer130&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;Select-Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;StartType&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;All three came back &lt;code&gt;Running / Automatic&lt;/code&gt; — already self-recovered before anyone looked. This told us the alert was valid but not actionable, and shifted focus to understanding root cause.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Step 02 — Map Service Transitions with Event ID 7036
&lt;/h2&gt;

&lt;p&gt;Windows logs every service state change — stopped, running, paused — as &lt;strong&gt;Event ID 7036&lt;/strong&gt; in the System log. Pull the last 20 transitions and sort them chronologically. This gives you the precise stop-and-start sequence and exact timestamps.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;Get-WinEvent&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-FilterHashtable&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;@{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nx"&gt;LogName&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'System'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;7036&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Where-Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="bp"&gt;$_&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Message&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-match&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'Your Service Name'&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Select-Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;TimeCreated&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Message&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;Sort-Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;TimeCreated&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Descending&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;Select-Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-First&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;20&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Read the output &lt;strong&gt;bottom-up&lt;/strong&gt; (oldest first). Look for the last time it went from &lt;code&gt;running → stopped&lt;/code&gt;, and whether it came back on its own or stayed down. Multiple stop/start cycles in quick succession often mean a crash-and-restart loop.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;🔵 &lt;strong&gt;SQL Server example:&lt;/strong&gt;&lt;/p&gt;


&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;Get-WinEvent&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-FilterHashtable&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;@{&lt;/span&gt;&lt;span class="nx"&gt;LogName&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'System'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="nx"&gt;Id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;7036&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;Where-Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="bp"&gt;$_&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Message&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-match&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s1"&gt;'SQL Server Agent \(MSSQLSERVER\)|SQL Server \(MSSQLSERVER\)|SQL Server Integration Services 13.0'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;Select-Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;TimeCreated&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Message&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;Sort-Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;TimeCreated&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Descending&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;Select-Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-First&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;20&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;The output showed all three services stopped at 10:20 AM IST and returned to running at 10:27 AM IST — a 6-minute outage that overlapped exactly with the alert timestamp.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Step 03 — Look for System-Level Triggers
&lt;/h2&gt;

&lt;p&gt;A service rarely stops in isolation. Before blaming the application, check whether the &lt;strong&gt;host itself&lt;/strong&gt; caused the stop. Four event IDs tell this story:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Event ID&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1074&lt;/td&gt;
&lt;td&gt;Intentional shutdown/restart — includes initiating process (TrustedInstaller, shutdown.exe, Ansible), user, and reason code&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6005&lt;/td&gt;
&lt;td&gt;Event log service started = OS finished booting. Your "server is up" timestamp&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6006&lt;/td&gt;
&lt;td&gt;Event log service stopped = OS going down. Pair with 6005 to measure reboot windows&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6008&lt;/td&gt;
&lt;td&gt;Unexpected/dirty shutdown — previous shutdown was unclean. A crash or power loss leaves this&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;Get-WinEvent&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-FilterHashtable&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;@{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nx"&gt;LogName&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'System'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1074&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;6005&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;6006&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;6008&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Select-Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;TimeCreated&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Message&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;Sort-Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;TimeCreated&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Descending&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;Select-Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-First&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;20&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c"&gt;# For recent 1074s with full detail:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;Get-WinEvent&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-FilterHashtable&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;@{&lt;/span&gt;&lt;span class="nx"&gt;LogName&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'System'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="nx"&gt;Id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1074&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;Where-Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="bp"&gt;$_&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;TimeCreated&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-gt&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Get-Date&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddHours&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;-24&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;Format-List&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;TimeCreated&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Message&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;🔵 &lt;strong&gt;SQL Server example:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Event 1074 revealed two reboots in the same maintenance window. The first was triggered by &lt;code&gt;o9ansibleuser&lt;/code&gt; via Ansible. The second was chained by &lt;code&gt;TrustedInstaller.exe&lt;/code&gt; with reason "Operating System: Upgrade (Planned)" — Windows Update had quietly queued a second reboot on top of the Ansible reboot. Without checking Event 1074, this would have looked like an unexplained outage.&lt;/p&gt;

&lt;p&gt;💡 If you find a &lt;strong&gt;6008 (dirty shutdown)&lt;/strong&gt; near your service stop, the host itself crashed — investigate the host before the service.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Step 04 — Read the Application's Own Logs
&lt;/h2&gt;

&lt;p&gt;Windows Event logs tell you &lt;strong&gt;when&lt;/strong&gt; the service stopped. The application's own logs tell you &lt;strong&gt;why&lt;/strong&gt;. Every serious Windows service writes its own log — find it and read the entries immediately before the service stopped.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Common log locations:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;# SQL Server → C:\Program Files\Microsoft SQL Server\MSSQL{ver}.{instance}\MSSQL\Log\ERRORLOG&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;# IIS        → C:\inetpub\logs\LogFiles\W3SVC1\&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c"&gt;# For services that write to Windows Application log:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;Get-WinEvent&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-FilterHashtable&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;@{&lt;/span&gt;&lt;span class="nx"&gt;LogName&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'Application'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="nx"&gt;Level&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;Where-Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="bp"&gt;$_&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ProviderName&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-match&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'YourService'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;Select-Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;TimeCreated&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Message&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;Sort-Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;TimeCreated&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Descending&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;Select-Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-First&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;20&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You're looking for one of three signatures:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Error/exception before stop&lt;/strong&gt; → crash&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Clean shutdown message&lt;/strong&gt; → planned stop&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Nothing unusual&lt;/strong&gt; → external trigger (reboot killed the process)&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;🔵 &lt;strong&gt;SQL Server example — ERRORLOG:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;SQL Server rotates its log on every restart. Find the file that covers your outage window by &lt;code&gt;LastWriteTime&lt;/code&gt;:&lt;/p&gt;


&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Find the right log file&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;Get-ChildItem&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"C:\Program Files\Microsoft SQL Server\MSSQL13.MSSQLSERVER\MSSQL\Log\ERRORLOG*"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;Select-Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;LastWriteTime&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Length&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;Sort-Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;LastWriteTime&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c"&gt;# Read the last 50 lines of the relevant file&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;Get-Content&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"...\MSSQL\Log\ERRORLOG.4"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Select-Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Last&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;50&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;The critical line at the tail of our log:&lt;/p&gt;


&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SQL Server is terminating in response to a 'stop' request from Service Control Manager.
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;That's a &lt;strong&gt;clean stop&lt;/strong&gt; — no crash, no error. Case closed on fault; focus shifts to who stopped it and why.&lt;/p&gt;

&lt;p&gt;⚠️ SQL ERRORLOG uses &lt;strong&gt;local server time&lt;/strong&gt;, not UTC. Convert your alert timestamp before searching.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Step 05 — Classify the Stop, Then Decide
&lt;/h2&gt;

&lt;p&gt;By now you have enough to classify into one of three categories:&lt;/p&gt;

&lt;h3&gt;
  
  
  🔴 Crash
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Exceptions/errors in app log immediately before stop&lt;/li&gt;
&lt;li&gt;Event 6008 (dirty shutdown) present&lt;/li&gt;
&lt;li&gt;Dump files in the app's log directory&lt;/li&gt;
&lt;li&gt;No clean stop message&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Response:&lt;/strong&gt; Don't just restart — find the root cause first. Check memory (&lt;code&gt;Get-Process&lt;/code&gt;), disk (&lt;code&gt;Get-PSDrive&lt;/code&gt;), dump files. Restarting a crashing service without fixing the cause fails again.&lt;/p&gt;

&lt;h3&gt;
  
  
  🟢 Clean Stop
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;"Stop request from SCM" in app log&lt;/li&gt;
&lt;li&gt;Config/agent disabled just before stop&lt;/li&gt;
&lt;li&gt;No preceding errors — manual or scripted&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Response:&lt;/strong&gt; Safe to restart, but find out who stopped it. Was it automation? Is it expected to auto-restart?&lt;/p&gt;

&lt;h3&gt;
  
  
  🟡 External Trigger
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Event 1074 near the stop time&lt;/li&gt;
&lt;li&gt;6005/6006 reboot pair visible&lt;/li&gt;
&lt;li&gt;Ansible, Windows Update, manual reboot&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Response:&lt;/strong&gt; The service is a passenger — the host was the cause. Verify the reboot was planned, confirm all services are back, close the ticket.&lt;/p&gt;




&lt;h2&gt;
  
  
  Going Further: From Reactive to Proactive
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;🔕 Maintenance Windows&lt;/strong&gt; — Before any planned reboot, open a monitoring suppression. Automate it as a pre-task in your Ansible playbook, not a manual step someone might forget.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;📋 Parse App Logs Continuously&lt;/strong&gt; — Ship application logs to a central store. Alert on &lt;code&gt;terminating&lt;/code&gt;, &lt;code&gt;severity 20+&lt;/code&gt;, &lt;code&gt;exception&lt;/code&gt; before a service hits the floor.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🧠 Watch Memory Before It Matters&lt;/strong&gt; — Many crashes are preceded by hours of memory pressure. A service paging to disk for 4 hours before crashing gave you warning you didn't act on.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🤖 Tag Automation in Monitoring&lt;/strong&gt; — Have Ansible write a comment to your alert system before rebooting. A ticket that says "Ansible reboot — expected" closes in seconds. One without context takes 15 minutes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;📅 Track TrustedInstaller Reboots&lt;/strong&gt; — Windows Update's chained reboots are invisible unless you watch Event 1074. Add a post-patch check that logs TrustedInstaller-initiated reboots to your CMDB.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;📈 Trend Restart Frequency&lt;/strong&gt; — A service that restarts once a quarter is healthy. One that restarts three times in a week has a problem. Track restart counts over time — the trend tells you before a crash does.&lt;/p&gt;




&lt;h2&gt;
  
  
  Quick Reference: The Diagnostic Playbook
&lt;/h2&gt;

&lt;p&gt;Save this to your runbook.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="c"&gt;# 1 — Current state&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;Get-Service&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ServiceA"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;"ServiceB"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Select-Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nx"&gt;Status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nx"&gt;StartType&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c"&gt;# 2 — Service transitions&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;Get-WinEvent&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-FilterHashtable&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;@{&lt;/span&gt;&lt;span class="nx"&gt;LogName&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'System'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="nx"&gt;Id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;7036&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;Where-Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="bp"&gt;$_&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Message&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-match&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'YourServiceName'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;Select-Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;TimeCreated&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nx"&gt;Message&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Sort-Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;TimeCreated&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Descending&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;Select-Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-First&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;20&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c"&gt;# 3 — Shutdown events&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;Get-WinEvent&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-FilterHashtable&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;@{&lt;/span&gt;&lt;span class="nx"&gt;LogName&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'System'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="nx"&gt;Id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1074&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;6005&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;6006&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;6008&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;Select-Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;TimeCreated&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nx"&gt;Id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nx"&gt;Message&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Sort-Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;TimeCreated&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Descending&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;Select-Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-First&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;20&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c"&gt;# 4 — App event log (errors/criticals)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;Get-WinEvent&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-FilterHashtable&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;@{&lt;/span&gt;&lt;span class="nx"&gt;LogName&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'Application'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="nx"&gt;Level&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;Where-Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="bp"&gt;$_&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ProviderName&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-match&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'YourService'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;Select-Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;TimeCreated&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nx"&gt;Message&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Select-Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-First&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;20&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c"&gt;# 5 — Server uptime&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Get-Date&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Get-CimInstance&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Win32_OperatingSystem&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;LastBootUpTime&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c"&gt;# SQL Server bonus — find the right ERRORLOG&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;Get-ChildItem&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"C:\Program Files\Microsoft SQL Server\MSSQL13.MSSQLSERVER\MSSQL\Log\ERRORLOG*"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;Select-Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nx"&gt;LastWriteTime&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Sort-Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;LastWriteTime&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;💡 The three root causes — crash, clean stop, external trigger — each have a different recovery path. &lt;strong&gt;Classify before you act&lt;/strong&gt;, and you'll never restart a service into the same problem twice.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;If you're dealing with something like this at work — or you have a war story of your own — I'm on &lt;a href="https://www.linkedin.com/in/prateeksrivastava123/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; and I actually respond.&lt;/p&gt;

&lt;p&gt;I publish one production incident breakdown every week — real commands, real dead ends, real fix. &lt;strong&gt;Follow on Medium&lt;/strong&gt; if you want the next one in your feed: &lt;a href="https://prateeksrivastav598.medium.com" rel="noopener noreferrer"&gt;prateeksrivastav598.medium.com&lt;/a&gt;&lt;/p&gt;

</description>
      <category>devops</category>
      <category>microsoft</category>
      <category>sql</category>
      <category>sre</category>
    </item>
    <item>
      <title>I Managed Kubernetes Across AWS, Azure, and GCP Simultaneously — Here's What Nobody Tells You</title>
      <dc:creator>Prateek Srivastava</dc:creator>
      <pubDate>Fri, 21 Aug 2026 19:11:46 +0000</pubDate>
      <link>https://dev.to/prateek_srivastava_6a5661/i-managed-kubernetes-across-aws-azure-and-gcp-simultaneously-heres-what-nobody-tells-you-2g69</link>
      <guid>https://dev.to/prateek_srivastava_6a5661/i-managed-kubernetes-across-aws-azure-and-gcp-simultaneously-heres-what-nobody-tells-you-2g69</guid>
      <description>&lt;p&gt;The day the same Helm chart behaved differently on three clouds in the same hour was the day I stopped trusting "cloud-agnostic" as a real thing.&lt;/p&gt;

&lt;p&gt;Nobody plans to manage Kubernetes on three clouds at the same time. It happens gradually — an acquisition brings an Azure footprint, a new business unit commits to GCP, and you already run EKS. Then one morning a page fires and you're staring at three terminal windows, three different cluster behaviours, one very angry incident bridge.&lt;/p&gt;

&lt;p&gt;I've spent the better part of two years in exactly that situation. What follows isn't a comparison chart you can find on any vendor blog. It's the stuff I learned the hard way — the silent differences that don't show up until something breaks in production at 2 AM.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;📟 The Incident That Started It All&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We deployed the same Helm chart — identical values, same image tag — to EKS, AKS, and GKE within the same 20-minute release window. EKS came up healthy. AKS came up healthy. GKE's pods started, ran for about 90 seconds, then began OOMKilling in a loop. Same YAML. Same limits. Three different outcomes. Four hours to find why. That story is lesson #3.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  1. Networking: The Biggest Lie — "Pods Are Just Pods"
&lt;/h2&gt;

&lt;p&gt;This is where most multi-cloud pain originates. Every Kubernetes tutorial tells you pods get their own IPs and can talk to each other. What it doesn't tell you is that &lt;em&gt;where those IPs come from&lt;/em&gt; completely changes your blast radius, subnet planning, security posture, and the failure modes you'll face at 3 AM.&lt;/p&gt;

&lt;h3&gt;
  
  
  EKS: Your pods eat your VPC subnet IPs
&lt;/h3&gt;

&lt;p&gt;EKS uses the AWS VPC CNI by default. Every pod gets a real, routable IP from your VPC subnet. This sounds fine until you have a &lt;code&gt;/24&lt;/code&gt; subnet and someone deploys a service with 200 replicas. The error isn't "out of IPs" — it's an ENI attachment timeout.&lt;/p&gt;

&lt;p&gt;The harder gotcha: each EC2 instance type has a max ENI count × max IPs per ENI cap. A &lt;code&gt;t3.medium&lt;/code&gt; can hold 3 ENIs × 6 IPs = 18 pod IPs max, minus 1 for the node. Pods sit &lt;strong&gt;Pending&lt;/strong&gt; on nodes with plenty of CPU and RAM — the constraint is invisible to the scheduler.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Check ENI and IP capacity on a node&lt;/span&gt;
kubectl describe node &amp;lt;node-name&amp;gt; | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-A5&lt;/span&gt; &lt;span class="s2"&gt;"Allocatable"&lt;/span&gt;

&lt;span class="c"&gt;# Check aws-node daemonset for ENI attachment errors&lt;/span&gt;
kubectl logs &lt;span class="nt"&gt;-n&lt;/span&gt; kube-system &lt;span class="nt"&gt;-l&lt;/span&gt; k8s-app&lt;span class="o"&gt;=&lt;/span&gt;aws-node &lt;span class="nt"&gt;--tail&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;50 | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="s2"&gt;"err&lt;/span&gt;&lt;span class="se"&gt;\|&lt;/span&gt;&lt;span class="s2"&gt;fail&lt;/span&gt;&lt;span class="se"&gt;\|&lt;/span&gt;&lt;span class="s2"&gt;exhaust"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; Enable VPC CNI prefix delegation — one ENI prefix = 16 IPs instead of 1.&lt;/p&gt;

&lt;h3&gt;
  
  
  AKS: Azure CNI pre-allocates IPs whether you like it or not
&lt;/h3&gt;

&lt;p&gt;AKS with Azure CNI reserves IPs per node based on &lt;code&gt;--max-pods&lt;/code&gt; (default 30) — before any pod runs. A 100-node cluster pre-consumes 3,000 VNet IPs. Use &lt;strong&gt;Azure CNI Overlay mode&lt;/strong&gt; if IP-constrained.&lt;/p&gt;

&lt;h3&gt;
  
  
  GKE: Clean until you need to peer networks
&lt;/h3&gt;

&lt;p&gt;GKE uses alias IP ranges, isolated from your main VPC. Clean story — until you peer your GKE VPC with on-prem and discover the pod CIDR overlaps your on-prem range, because you let GKE auto-assign ranges six months ago. &lt;strong&gt;Always explicitly define secondary ranges.&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;EKS&lt;/th&gt;
&lt;th&gt;AKS&lt;/th&gt;
&lt;th&gt;GKE&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Pod IP source&lt;/td&gt;
&lt;td&gt;VPC subnet (real IPs)&lt;/td&gt;
&lt;td&gt;VNet or overlay&lt;/td&gt;
&lt;td&gt;Alias IP ranges&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IP exhaustion risk&lt;/td&gt;
&lt;td&gt;High — ENI limits&lt;/td&gt;
&lt;td&gt;High — pre-allocated&lt;/td&gt;
&lt;td&gt;Low — isolated&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Common 3 AM failure&lt;/td&gt;
&lt;td&gt;ENI attachment timeout&lt;/td&gt;
&lt;td&gt;VNet IP exhaustion&lt;/td&gt;
&lt;td&gt;CIDR overlap during peering&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  2. IAM + RBAC: Three Identity Models, One Misconfiguration Away from Disaster
&lt;/h2&gt;

&lt;h3&gt;
  
  
  EKS: The IRSA silent fallback trap
&lt;/h3&gt;

&lt;p&gt;If your IRSA annotation has a typo, the assume-role call silently fails and the pod falls through to the node's instance profile — often over-permissive. You won't see an error. Always verify:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; &amp;lt;pod-name&amp;gt; &lt;span class="nt"&gt;--&lt;/span&gt; aws sts get-caller-identity
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I once spent three hours debugging why a pod had too much S3 access. A typo in the annotation. Silent fallback to the node's IAM role. The pod happily worked — with the wrong permissions.&lt;/p&gt;

&lt;h3&gt;
  
  
  AKS: Workload Identity federation — fragile on setup
&lt;/h3&gt;

&lt;p&gt;Three pieces must align exactly: Managed Identity, federated credential (exact OIDC issuer URL, including trailing slashes), and the Kubernetes service account annotation. One mismatch = silent 401.&lt;/p&gt;

&lt;h3&gt;
  
  
  GKE: Node rotation breaks implicit identity
&lt;/h3&gt;

&lt;p&gt;Enabling Workload Identity on a node pool removes the node's default Google service account. Any workload relying on implicit node identity breaks on the next node rotation. Audit before enabling.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. Memory + cgroups: Why the Same Container OOMKilled on GKE but Not on EKS
&lt;/h2&gt;

&lt;p&gt;Here's the opening incident. Same image, same limits, EKS and AKS healthy, GKE OOMKilling every 90 seconds.&lt;/p&gt;

&lt;p&gt;GKE had moved to containerd with &lt;strong&gt;cgroup v2&lt;/strong&gt; on newer node images. EKS and AKS were still on cgroup v1.&lt;/p&gt;

&lt;p&gt;Our Java service used JVM ergonomics to auto-detect heap size:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;cgroup v1:&lt;/strong&gt; JVM reads from &lt;code&gt;/sys/fs/cgroup/memory/memory.limit_in_bytes&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;cgroup v2:&lt;/strong&gt; JVM reads from &lt;code&gt;/sys/fs/cgroup/memory.max&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Our old JVM didn't handle cgroup v2. It read &lt;strong&gt;host&lt;/strong&gt; memory (64GB) instead of the container limit (2GB), allocated an 8GB heap into a 2GB container, and OOMKilled within 90 seconds of starting.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Check which cgroup version the container sees&lt;/span&gt;
kubectl &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; &amp;lt;pod-name&amp;gt; &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="nb"&gt;cat&lt;/span&gt; /proc/1/cgroup
&lt;span class="c"&gt;# cgroup v1: "12:memory:/kubepods/..."&lt;/span&gt;
&lt;span class="c"&gt;# cgroup v2: single line "0::/"&lt;/span&gt;

&lt;span class="c"&gt;# Check what heap the JVM actually allocated&lt;/span&gt;
kubectl &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; &amp;lt;pod-name&amp;gt; &lt;span class="nt"&gt;--&lt;/span&gt; java &lt;span class="nt"&gt;-XshowSettings&lt;/span&gt;:all &lt;span class="nt"&gt;-version&lt;/span&gt; 2&amp;gt;&amp;amp;1 | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; heap

&lt;span class="c"&gt;# See OOMKill events across all namespaces&lt;/span&gt;
kubectl get events &lt;span class="nt"&gt;--field-selector&lt;/span&gt; &lt;span class="nv"&gt;reason&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;OOMKilling &lt;span class="nt"&gt;-A&lt;/span&gt; &lt;span class="nt"&gt;--sort-by&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'.lastTimestamp'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; JDK 15+ (native cgroup v2 support) or JDK 11 with &lt;code&gt;-XX:+UseContainerSupport&lt;/code&gt;. Always explicitly set &lt;code&gt;-Xmx&lt;/code&gt; and &lt;code&gt;-Xms&lt;/code&gt;. This isn't just a Java problem — Go's &lt;code&gt;GOMAXPROCS&lt;/code&gt; and Python's &lt;code&gt;multiprocessing.cpu_count()&lt;/code&gt; have the same pattern.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;EKS&lt;/th&gt;
&lt;th&gt;AKS&lt;/th&gt;
&lt;th&gt;GKE&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Default node OS&lt;/td&gt;
&lt;td&gt;Amazon Linux 2023&lt;/td&gt;
&lt;td&gt;Ubuntu 22.04 / Azure Linux&lt;/td&gt;
&lt;td&gt;Container-Optimized OS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;cgroup version&lt;/td&gt;
&lt;td&gt;v2 (AL2023), v1 (AL2)&lt;/td&gt;
&lt;td&gt;v2 (Ubuntu 22.04+)&lt;/td&gt;
&lt;td&gt;v2 (COS since mid-2022)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  4. Storage: The AZ-Pinning Trap
&lt;/h2&gt;

&lt;p&gt;Block storage (EBS / Azure Disk / Persistent Disk) is AZ-specific on every cloud. Your PVC and the pod using it must be in the same AZ.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The scenario I've watched happen three times:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Stateful pod uses a PVC in AZ-A. Traffic grows. Cluster Autoscaler spins up nodes in AZ-B and AZ-C. New pods stay &lt;strong&gt;Pending&lt;/strong&gt; — PVC is in AZ-A, the new nodes aren't. On-call engineer stares at CPU and memory graphs seeing nothing wrong.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# The event buried in pod describe that tips you off&lt;/span&gt;
kubectl describe pod &amp;lt;pending-pod&amp;gt; | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="s2"&gt;"had volume node affinity conflict"&lt;/span&gt;
&lt;span class="c"&gt;# "0/12 nodes are available: 8 node(s) had volume node affinity conflict"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; Use &lt;code&gt;volumeBindingMode: WaitForFirstConsumer&lt;/code&gt; on all storage classes. Delays PV creation until pod scheduling — volume always lands in the same AZ as the pod.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. Load Balancers: Same Service Type, Three Different Outcomes
&lt;/h2&gt;

&lt;p&gt;Each cloud's controller uses completely different annotation namespaces for the same intent:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;annotations&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="c1"&gt;# EKS — NLB instead of legacy Classic ELB&lt;/span&gt;
  &lt;span class="na"&gt;service.beta.kubernetes.io/aws-load-balancer-type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;external"&lt;/span&gt;
  &lt;span class="na"&gt;service.beta.kubernetes.io/aws-load-balancer-nlb-target-type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ip"&lt;/span&gt;

  &lt;span class="c1"&gt;# AKS — internal (private) load balancer&lt;/span&gt;
  &lt;span class="na"&gt;service.beta.kubernetes.io/azure-load-balancer-internal&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;true"&lt;/span&gt;

  &lt;span class="c1"&gt;# GKE — completely different namespace&lt;/span&gt;
  &lt;span class="na"&gt;networking.gke.io/load-balancer-type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Internal"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;⚠️ We once deployed a chart to GKE with only AWS annotations. GKE ignored them and created a &lt;strong&gt;public&lt;/strong&gt; Load Balancer. An internal API was internet-reachable for 40 minutes. SolarWinds monitoring caught it. It's the kind of miss that ends careers if the service is sensitive.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rule:&lt;/strong&gt; Validate LB visibility (internal vs public) on all three clouds in CI.&lt;/p&gt;




&lt;h2&gt;
  
  
  6. Autoscaling: Cluster Autoscaler Is Not the Same Everywhere
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;EKS scale-up path:&lt;/strong&gt; CA detects unschedulable pods → calls ASG → ASG launches EC2 → joins cluster → kubelet registers → pods schedule. That's &lt;strong&gt;4–8 minutes&lt;/strong&gt; minimum.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GKE Node Auto Provisioning (NAP):&lt;/strong&gt; Managed by Google, reacts faster, can create new node pools automatically. Gotcha: NAP creates pools with labels and taints you didn't ask for. Pods without matching tolerations won't schedule — even though the cluster "scaled up" in your dashboards.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What works across all three:&lt;/strong&gt; Layer KEDA (application-level scaling, seconds) under Cluster Autoscaler (node-level, minutes). Scale pods first; nodes are the last resort.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I'd Tell Myself Before Starting All Over
&lt;/h2&gt;

&lt;p&gt;Multi-cloud Kubernetes isn't twice the work — it's about six times the work, because every subtle difference compounds.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Standardise observability first.&lt;/strong&gt; Before you standardise deployments, standardise how you look at your clusters. Same dashboards, same alert expressions, same log structure. When the incident fires at 2 AM, you want muscle memory, not translation overhead.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Document differences, not just similarities.&lt;/strong&gt; Your runbooks should say "on EKS, check X; on AKS, check Y; on GKE, check Z" — not pretend the clouds are the same.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Test Helm charts on all three before every major release.&lt;/strong&gt; 20 minutes of CI is cheaper than one 4-hour incident.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Never trust "cloud-agnostic" on the label.&lt;/strong&gt; Especially networking, storage, and identity. Those break silently rather than loudly.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The day you stop being surprised by cloud differences is the day you've actually become a multi-cloud SRE. Everything before that is just surviving the learning curve.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;&lt;em&gt;If you're just starting this journey: keep a war journal. Every weird behaviour, every gotcha that cost you an hour — write it down. In six months it's worth more than any certification.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Follow me on &lt;a href="https://prateeksrivastav598.medium.com/" rel="noopener noreferrer"&gt;Medium&lt;/a&gt; for more incident stories from production.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>devops</category>
      <category>aws</category>
      <category>cloud</category>
    </item>
    <item>
      <title>Our EKS Node Crashed and Four Auto-Recovery Mechanisms All Failed. Here's Why.</title>
      <dc:creator>Prateek Srivastava</dc:creator>
      <pubDate>Thu, 20 Aug 2026 11:56:58 +0000</pubDate>
      <link>https://dev.to/prateek_srivastava_6a5661/our-eks-node-crashed-and-four-auto-recovery-mechanisms-all-failed-heres-why-93l</link>
      <guid>https://dev.to/prateek_srivastava_6a5661/our-eks-node-crashed-and-four-auto-recovery-mechanisms-all-failed-heres-why-93l</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;⚡ TL;DR: An EKS worker node running 30+ pods crashed at 08:43 IST on Aug 16. EC2 Auto Scaling didn't act. EKS Node Auto Repair was never enabled. Cluster Autoscaler had no headroom (Min=Max=6). Our memory alert fired 82 seconds after the node was already dead. We fixed it manually at 12:30 IST — 4 hours later. Every fix is one or two CLI commands. Here's the full breakdown.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;When an EKS worker node goes down, Kubernetes is supposed to handle it. That's the whole pitch — self-healing infrastructure. Pods evict, workloads reschedule, the cluster heals itself.&lt;/p&gt;

&lt;p&gt;In a recent incident, a node running 30+ pods crashed at 08:43 IST. None of the four auto-recovery mechanisms we had in place did anything. The node sat NotReady for almost 4 hours. We discovered it 82 seconds after it died — from a memory alert that fired when the node was already gone — and fixed it manually at 12:30 IST.&lt;/p&gt;

&lt;p&gt;The interesting part wasn't that the node crashed. It was that four different layers of protection failed for four completely different reasons.&lt;/p&gt;

&lt;p&gt;Here's exactly what failed and why.&lt;/p&gt;

&lt;p&gt;The Node That Looked Healthy Until It Didn't&lt;/p&gt;

&lt;p&gt;ip-10-&lt;em&gt;-&lt;/em&gt;-*.ec2.internal had been running since Jun 28. From Kubernetes' perspective, it was Ready. CPU requests at ~97%. Memory requests at ~69%. Nothing alarming.&lt;/p&gt;

&lt;p&gt;The actual picture was very different:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Allocated resources:
  Resource    Requests       Limits
  cpu         ~97%           ~545%
  memory      ~69%           ~358%
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;358% memory limit overcommit. Kubernetes scheduled 37 pods there because requests showed 69% — but if those pods pushed toward their limits, the node had no chance. The requests were lies; the limits were the truth. And the truth said this node was 3.5x overloaded.&lt;/p&gt;

&lt;p&gt;Underneath the Ready status, the containerd runtime had been in a degraded state since Jul 20, when the OOM killer had hard-killed a MongoDB process. The kernel had logged two containerd-shim deadlocks (Jul 1 and Jul 29) that the node had somehow absorbed. Neither showed up anywhere in monitoring. The control plane saw nothing wrong.&lt;/p&gt;

&lt;p&gt;On Aug 16 at 08:22 IST, a service responsible for processing audit events started leaking memory. ELK showed node memory at 81.6% at 08:22:57 IST. By 08:43 IST the service had grown from 2.0GB to 6.2GB — a 4.2GB spike in 21 minutes — pushing the node from ~81% to ~96%.&lt;/p&gt;

&lt;p&gt;The memory pressure triggered a third containerd-shim deadlock on the already-corrupted runtime. This time it was fatal. At 08:43:22 IST, SSM lost contact. Kubelet posted its last heartbeat. At 08:45:10, the node went NotReady.&lt;/p&gt;




&lt;p&gt;Now watch how every auto-recovery mechanism missed it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Failure #1 — EC2 Auto Scaling Health Check&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The ASG protecting this nodegroup was configured with EC2-level health checks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;HealthCheckType: EC2
Min: 6 | Max: 6 | Desired: 6
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;EC2 health checks have exactly one question: is the VM powered on?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws ec2 describe-instance-status &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--instance-ids&lt;/span&gt; &amp;lt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;--region&lt;/span&gt; &amp;lt;region&amp;gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--query&lt;/span&gt; &lt;span class="s1"&gt;'InstanceStatuses[].[InstanceState.Name,SystemStatus.Status,InstanceStatus.Status]'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--output&lt;/span&gt; table
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;+---------+------+------+
|  running|  ok  |  ok  |
+---------+------+------+
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The instance was running. System status: ok. Instance status: ok. The AWS hypervisor was satisfied. The deadlock inside containerd was completely invisible at the hypervisor layer — the kernel was alive, the VM was up, the NIC was responding to health probes.&lt;/p&gt;

&lt;p&gt;EC2 health check never triggered. No replacement instance was launched.&lt;/p&gt;

&lt;p&gt;The lesson: EC2 health checks only detect hardware failure or VM termination. They cannot detect OS-level hangs, kubelet death, containerd deadlocks, or any software failure that doesn't take down the underlying VM. For Kubernetes node health, EC2 checks are nearly useless.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Failure #2 — EKS Node Auto Repair&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;EKS Node Auto Repair is designed exactly for this scenario. When a node stays NotReady for a defined period, it automatically cordons, drains, and replaces it. No manual intervention needed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws eks describe-nodegroup &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--cluster-name&lt;/span&gt; &amp;lt;name&amp;gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--nodegroup-name&lt;/span&gt; &amp;lt;nodegroup_name&amp;gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--query&lt;/span&gt; &lt;span class="s1"&gt;'nodegroup.nodeRepairConfig'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;null. Never configured. Never enabled.&lt;/p&gt;

&lt;p&gt;This feature was available. We had just never set it up. The node sat NotReady for nearly 4 hours while the feature that would have replaced it in 10 minutes was turned off by default.&lt;/p&gt;

&lt;p&gt;The lesson: EKS Node Auto Repair is not enabled by default. Check every nodegroup right now with the command above. If you get null, you have this gap.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Failure #3 — Cluster Autoscaler&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The cluster autoscaler was running. It's supposed to handle exactly this kind of situation. But our configuration made it powerless:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Min: 6 | Max: 6 | Desired: 6
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Min equals Max. The autoscaler has no headroom to operate. To replace a broken node, it needs to launch a new one first (going to 7, violating Max), drain the broken node, then terminate it (back to 6). With Max=6, it couldn't even start that sequence.&lt;/p&gt;

&lt;p&gt;The autoscaler logs confirmed it saw the problem — and couldn't act:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;I0817 12:17:57 pre_filtering_processor.go:67]
Skipping ip-*-*-*-*.ec2.internal — node group min size reached
(current: 6, min: 6)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It knew the node was bad. It had no authority to fix it.&lt;/p&gt;

&lt;p&gt;There was a second problem: the cluster-autoscaler pod itself was running on the broken node, stuck in Terminating state alongside 25+ other pods.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kube-system  cluster-autoscaler-5********8  1/1  Terminating  0  6d5h
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The thing responsible for replacing the broken node was stuck on the broken node.&lt;/p&gt;

&lt;p&gt;The lesson: Min=Max is a zero-headroom configuration that paralyzes automated recovery. Set Max to at least Min+2 on every nodegroup.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Failure #4 — Memory Alert (Fired Too Late to Matter)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We had a memory alert configured — running on an 11-minute cron interval, watching for node memory usage above 95%.&lt;/p&gt;

&lt;p&gt;ELK showed the node at 81.6% for hours before the incident:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;IST timestamp    Node memory %
08:22:57         81.6%
08:33:57         81.6%
08:44:57         80.6%  ← node already down, stale value
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The 4.2GB memory spike happened entirely between two check cycles. At 08:22 the node was fine. At 08:44 the check returned stale data because the node was already gone.&lt;/p&gt;

&lt;p&gt;The alert fired at 08:44 IST. The node went unreachable at 08:43:22 IST. The alert was 82 seconds behind.&lt;/p&gt;

&lt;p&gt;This is a structural problem: the metric source is the node itself. When the node dies, metrics stop. If the crash happens between alert evaluation cycles, you miss it entirely. The faster a node crashes, the more likely it dies between evaluations.&lt;/p&gt;

&lt;p&gt;The lesson: Metric-based node alerts have a fundamental blind spot. If the node is the source of the metric, the metric disappears when the node dies.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;What We're Fixing&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Enable EKS Node Auto Repair (do this first)
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws eks update-nodegroup-config &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--cluster-name&lt;/span&gt; &amp;lt;name&amp;gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--nodegroup-name&lt;/span&gt; &amp;lt;nodegroup_name&amp;gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--node-repair-config&lt;/span&gt; &lt;span class="nv"&gt;enabled&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--region&lt;/span&gt; us-east-1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When a node stays NotReady for the configured threshold, EKS automatically cordons, drains, and replaces it. The control plane makes this decision — it doesn't depend on the broken node reporting its own failure.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Set Max &amp;gt; Min on Every ASG
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws autoscaling update-auto-scaling-group &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--auto-scaling-group-name&lt;/span&gt; &amp;lt;name&amp;gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--min-size&lt;/span&gt; 6 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--max-size&lt;/span&gt; 8 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--region&lt;/span&gt; us-east-1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Max needs to be at least Min+2 to give the autoscaler room to launch a replacement before removing the broken instance.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Switch to ELB Health Checks
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws autoscaling update-auto-scaling-group &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--auto-scaling-group-name&lt;/span&gt; &amp;lt;name&amp;gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--health-check-type&lt;/span&gt; ELB &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--health-check-grace-period&lt;/span&gt; 300 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--region&lt;/span&gt; us-east-1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ELB health checks evaluate actual application-layer response, not just hypervisor state.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Replace Metric-Based Node Alert with Condition-Based Alert
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# This fires even when the node is completely dead.&lt;/span&gt;
&lt;span class="c1"&gt;# kube-state-metrics reads from the API server, not from the node itself.&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;alert&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;NodeNotReady&lt;/span&gt;
  &lt;span class="na"&gt;expr&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;kube_node_status_condition{condition="Ready",status="true"} == &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;
  &lt;span class="na"&gt;for&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;90s&lt;/span&gt;
  &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;severity&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;critical&lt;/span&gt;
  &lt;span class="na"&gt;annotations&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;summary&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Node&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;$labels.node&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;NotReady&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;for&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;gt;90s&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;—&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;EKS&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Auto&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Repair&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;should&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;engage"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;kube-state-metrics watches the Kubernetes API server — not the node. It fires even when the node is completely unreachable.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Enforce Memory Overcommit Limits
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;yaml&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;LimitRange&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;memory-ratio-limit&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;your-namespace&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;limits&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Container&lt;/span&gt;
    &lt;span class="na"&gt;maxLimitRequestRatio&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;memory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;4"&lt;/span&gt;   &lt;span class="c1"&gt;# limit cannot exceed 4x request&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This forces the actual memory ceiling to stay within a predictable range of what the scheduler sees. A pod with a 1Gi request cannot have a 16Gi limit.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;The Broader Problem&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This wasn't an unusual incident. A node accumulated damage silently for 46 days. Nothing alerted. Nothing flagged the degraded containerd state. The node reported Ready to the control plane while internally the runtime was already compromised.&lt;/p&gt;

&lt;p&gt;When the fatal event came — a memory spike from an unrelated service — four recovery mechanisms failed in different ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;EC2 health checks were asking the wrong question (is the VM up?)&lt;/li&gt;
&lt;li&gt;EKS Auto Repair was never turned on&lt;/li&gt;
&lt;li&gt;The autoscaler had no room to maneuver (Min=Max)&lt;/li&gt;
&lt;li&gt;The metric-based alert fired 82 seconds after the node was already dead&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Any one of these gaps would have slowed recovery. All four together meant 4 hours of a NotReady node and a manual reboot at noon.&lt;/p&gt;

&lt;p&gt;The fixes are each one or two commands. None of them are complicated. They just require knowing the gaps exist.&lt;/p&gt;

&lt;p&gt;Check Your Cluster Right Now&lt;/p&gt;

&lt;p&gt;Run this on every nodegroup:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws eks describe-nodegroup &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--cluster-name&lt;/span&gt; &amp;lt;your-cluster&amp;gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--nodegroup-name&lt;/span&gt; &amp;lt;your-nodegroup&amp;gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--query&lt;/span&gt; &lt;span class="s1"&gt;'nodegroup.nodeRepairConfig'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you get null — you have this gap. Fix it before the next 2 AM alert.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The names, cluster/node identifiers, timestamps, instance IDs, pod counts, resource values, and other incident-specific details in this article have been intentionally changed or fictionalized for privacy and security. The failure pattern and technical lessons remain representative of the original incident.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;Follow me on &lt;a href="https://prateeksrivastav598.medium.com/" rel="noopener noreferrer"&gt;Medium&lt;/a&gt; for more incident stories from production.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>devops</category>
      <category>aws</category>
      <category>sre</category>
    </item>
  </channel>
</rss>
