In 2026, the major cloud providers collectively experienced over 300 distinct operational incidents. Most lasted under an hour. Several lasted long enough to become post-mortems. None of them were predictable from inside your own infrastructure — they became visible only when your external-facing services started failing.
The teams that recovered fastest had one thing in common: they knew about the outage before their users did.
This guide covers how to build that awareness.
The Limits of Cloud Provider Status Pages
Every major cloud provider maintains a status page. The problem is that status pages are self-reported, often delayed, and historically optimistic during active incidents.
A well-documented pattern: a provider's status page shows "All Systems Operational" while engineers on Twitter are reporting widespread failures. The status page update comes 15–20 minutes after the incident starts — after the on-call team has confirmed, triaged, and written a public-facing message that doesn't alarm customers more than necessary.
This doesn't mean status pages are useless. They're authoritative when they report a problem. But they're not reliable as a first-alert mechanism.
Data Sources by Provider
AWS
AWS maintains status.aws.amazon.com. The main status page is HTML-only, but two machine-readable feeds exist:
RSS/Atom per-service feeds:
https://status.aws.amazon.com/rss/ec2-us-east-1.rss
https://status.aws.amazon.com/rss/lambda-us-east-1.rss
https://status.aws.amazon.com/rss/s3-us-east-1.rss
Each feed covers a single service + region combination. There are hundreds of them.
AWS Health API (requires AWS account):
aws health describe-events \
--filter '{"eventStatusCodes":["open","upcoming"]}' \
--region us-east-1
The AWS Health API gives you personalized health events — incidents affecting services your account is actually using. For monitoring your own infrastructure this is the gold standard, but it requires credentials.
Google Cloud Platform
GCP publishes a JSON incident feed:
https://status.cloud.google.com/incidents.json
Each incident object has a begin timestamp and, when resolved, an end timestamp. An active outage has no end field:
const res = await fetch('https://status.cloud.google.com/incidents.json');
const incidents = await res.json();
const active = incidents.filter(i => !i.end);
The feed is updated in near real-time (typically within 10 minutes of an incident starting).
Microsoft Azure
Azure uses status.azure.com. Like AWS, it's primarily HTML, but RSS feeds exist:
https://azurestatuscdn.azureedge.net/en-us/status/feed/
Azure also has a REST API for service health in their Resource Manager:
az rest --method get \
--url "https://management.azure.com/providers/Microsoft.ResourceHealth/events?api-version=2022-10-01"
Cloudflare, GitHub, Vercel
These three use Atlassian Statuspage, which exposes a clean JSON API:
https://www.githubstatus.com/api/v2/status.json
https://www.cloudflarestatus.com/api/v2/status.json
https://www.vercel-status.com/api/v2/status.json
The status response looks like:
{
"status": {
"indicator": "none", // "none" | "minor" | "major" | "critical"
"description": "All Systems Operational"
}
}
Unresolved incidents:
https://www.githubstatus.com/api/v2/incidents/unresolved.json
Latency Probing: Don't Wait for the Status Page
The most reliable early-warning system is not reading status pages — it's actively probing the provider's API gateway and measuring latency.
A sudden spike in response time to ec2.amazonaws.com, storage.googleapis.com, or management.azure.com often precedes any official incident report by 5–15 minutes.
A minimal Node.js gateway prober:
const PROBES = [
{ name: 'AWS', url: 'https://ec2.amazonaws.com/ping' },
{ name: 'GCP', url: 'https://storage.googleapis.com/' },
{ name: 'Azure', url: 'https://management.azure.com/' },
{ name: 'Cloudflare', url: 'https://1.1.1.1/cdn-cgi/trace' },
{ name: 'GitHub', url: 'https://api.github.com/zen' },
{ name: 'Vercel', url: 'https://vercel.com/api/v1/health' },
];
async function probe(target) {
const t0 = Date.now();
const controller = new AbortController();
setTimeout(() => controller.abort(), 8000);
try {
const res = await fetch(target.url, {
signal: controller.signal,
cache: 'no-store',
});
return { name: target.name, latencyMs: Date.now() - t0, status: res.status };
} catch (err) {
return { name: target.name, latencyMs: null, error: String(err) };
}
}
// Run every 60 seconds
setInterval(() => {
Promise.all(PROBES.map(probe)).then(results => {
results.forEach(r => {
if (!r.latencyMs || r.latencyMs > 3000) {
alertOncall(r);
}
});
});
}, 60_000);
DeveloperLab's Cloud Outage Map uses exactly this approach — combining official status feeds with active gateway pings every 3 minutes, surfacing discrepancies when a provider's feed says "none" but gateway latency is elevated.
Building an Incident Alerting Pipeline
Threshold-based alerting
Don't alert on every latency fluctuation. Set a baseline and alert on deviations:
const LATENCY_BASELINE = {
AWS: 80, // ms p50 for ec2.amazonaws.com
GCP: 60,
Azure: 90,
Cloudflare: 20,
GitHub: 120,
Vercel: 80,
};
const ALERT_MULTIPLIER = 3.0; // alert at 3× baseline
function shouldAlert(provider, latencyMs) {
return latencyMs > LATENCY_BASELINE[provider] * ALERT_MULTIPLIER;
}
Confirmation before alerting
Single-sample failures are noisy. Run two probes 30 seconds apart before firing an alert:
let suspectedIncidents = new Map();
function checkAndAlert(provider, latencyMs) {
if (shouldAlert(provider, latencyMs)) {
if (suspectedIncidents.has(provider)) {
// Second consecutive failure — fire alert
sendAlert({ provider, latencyMs });
suspectedIncidents.delete(provider);
} else {
// First failure — wait and confirm
suspectedIncidents.set(provider, { latencyMs, detectedAt: Date.now() });
}
} else {
// Recovery — clear suspicion
suspectedIncidents.delete(provider);
}
}
Enriching alerts with status page context
When you fire an alert, automatically fetch the current status page indicator to give responders immediate context:
async function sendAlert({ provider, latencyMs }) {
const statusPageIndicator = await fetchStatusIndicator(provider);
const message = [
`🔴 ${provider} gateway latency spike`,
`Measured: ${latencyMs}ms (baseline: ${LATENCY_BASELINE[provider]}ms)`,
`Official status: ${statusPageIndicator}`,
statusPageIndicator === 'none'
? '⚠️ Not yet reflected on status page' : '',
].filter(Boolean).join('\n');
await postToSlack(message);
await postToPagerDuty(message);
}
What to Do During a Cloud Provider Outage
Immediate (0–5 minutes)
- Confirm it's the provider, not you. Check your own deployment pipeline, recent releases, and database health. Don't wait for the status page.
- Open the provider's incident history. The pattern of previous outages tells you which services typically cascade (e.g., IAM failures in AWS affect almost everything downstream).
- Identify the blast radius. Which of your services depend on the affected region/service? Not all outages are global.
Short-term (5–30 minutes)
- Enable read-from-cache mode. If your architecture supports it, serve stale data rather than failing entirely.
- Degrade gracefully. Disable non-critical features that depend on the affected service. A payment outage doesn't have to take down your entire app.
- Communicate proactively. Post an incident on your status page before customers contact support. "We are aware of an ongoing issue with our payment provider and are monitoring" is better than silence.
Recovery
- Don't assume recovery is instant. Cloud outages often have a "flapping" phase where services appear recovered but still fail intermittently. Keep enhanced monitoring on for 30 minutes post-resolution.
- Write the post-mortem. Even for third-party incidents. Document the detection time, impact, actions taken, and how you'll reduce blast radius next time.
Incident Frequency by Provider (2025–2026)
Based on public incident feeds:
| Provider | Major incidents | Avg resolution time | Longest incident |
|---|---|---|---|
| AWS (us-east-1) | 7 | 1h 42min | 4h 18min |
| GCP (global) | 5 | 58min | 2h 44min |
| Azure (global) | 9 | 2h 11min | 6h 30min |
| Cloudflare | 4 | 34min | 1h 22min |
| GitHub | 11 | 22min | 1h 08min |
| Vercel | 6 | 41min | 2h 05min |
GitHub has the highest incident frequency but the fastest resolution. Azure has the longest individual incidents. us-east-1 remains AWS's most outage-prone region — a fact that has held true for over a decade.
Checklist: Outage-Resilient Architecture
- Multi-region deployments for critical services
- Circuit breakers on all external dependencies
- Async task queues so work can be retried after recovery
- Graceful degradation — identify which features can be disabled cleanly
- Cache layers with configurable stale-serving thresholds
- Status page for your own service (not just your infrastructure)
- Runbook per provider — what to do when AWS us-east-1 goes down vs. a global Cloudflare incident
- Active probing — don't rely solely on provider status pages for first awareness
Cloud infrastructure failing is a design constraint, not an edge case. The teams with the shortest time-to-awareness and the clearest runbooks recover fastest. Build the monitoring before you need it.