<?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: Kerolos Atallah</title>
    <description>The latest articles on DEV Community by Kerolos Atallah (@kerolos_atallah).</description>
    <link>https://dev.to/kerolos_atallah</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%2F4034583%2F2f750b6b-acd5-4eb2-a291-962e979b8e98.jpg</url>
      <title>DEV Community: Kerolos Atallah</title>
      <link>https://dev.to/kerolos_atallah</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kerolos_atallah"/>
    <language>en</language>
    <item>
      <title>I read 172 official status feeds every 10 minutes. Here is what is quietly broken in them.</title>
      <dc:creator>Kerolos Atallah</dc:creator>
      <pubDate>Wed, 05 Aug 2026 17:00:52 +0000</pubDate>
      <link>https://dev.to/kerolos_atallah/i-read-172-official-status-feeds-every-10-minutes-here-is-what-is-quietly-broken-in-them-4234</link>
      <guid>https://dev.to/kerolos_atallah/i-read-172-official-status-feeds-every-10-minutes-here-is-what-is-quietly-broken-in-them-4234</guid>
      <description>&lt;p&gt;For the last few weeks I've had a cron job reading the official status feed of 172 cloud and SaaS providers every ten minutes. Not scraping their HTML, not counting tweets, just reading the machine-readable source each vendor publishes about itself.&lt;/p&gt;

&lt;p&gt;I wrote about the first version of this in July, when it was 96 providers. This is what another 76 vendors and a month of collected data added, and most of it is stranger than the first batch.&lt;/p&gt;

&lt;p&gt;I expected the hard part to be scale. It wasn't. The hard part is that "the official status feed" is not one thing, and several of them are quietly broken in ways their own vendors seem not to know about.&lt;/p&gt;

&lt;h2&gt;
  
  
  There is no standard, and it isn't close
&lt;/h2&gt;

&lt;p&gt;Statuspage's &lt;code&gt;/api/v2/summary.json&lt;/code&gt; is the closest thing the industry has to a convention, and it covers most but not all of what I track. The rest need their own parsers. Google publishes a dashboard &lt;code&gt;incidents.json&lt;/code&gt; in its own shape, AWS has a health event feed, Azure emits RSS, Slack has a bespoke API, Oracle Cloud has a region-by-service matrix, Status.io has its own API, and Instatus serves a near-copy of Statuspage's format.&lt;/p&gt;

&lt;p&gt;That last one is the instructive case. Instatus exposes &lt;code&gt;/api/v2/summary.json&lt;/code&gt; at the same path as Statuspage, and it parses, but it omits the &lt;code&gt;components&lt;/code&gt; array, &lt;code&gt;page.updated_at&lt;/code&gt;, and the incident archive. A parser written against Statuspage will happily consume it and conclude that a vendor with a live outage has no components and nothing wrong. Compatible-looking is worse than incompatible.&lt;/p&gt;

&lt;h2&gt;
  
  
  AWS ships its status feed in UTF-16, big-endian
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;https://status.aws.amazon.com/data.json&lt;/code&gt; redirects to &lt;code&gt;health.aws.amazon.com/public/currentevents&lt;/code&gt; and returns a body that starts with the bytes &lt;code&gt;FE FF&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;That's a UTF-16 big-endian BOM. Not UTF-8. Not even the little-endian UTF-16 you'd occasionally expect from a Windows toolchain. &lt;code&gt;response.text()&lt;/code&gt; in a browser or Node will not give you usable JSON, and neither will a naive UTF-8 decode. You get a string of interleaved null bytes and a parse error that looks like the endpoint is down.&lt;/p&gt;

&lt;p&gt;Everyone consuming this feed has independently discovered this and written the same three-branch decoder. It has apparently been this way for years.&lt;/p&gt;

&lt;h2&gt;
  
  
  Stripe's status JSON has said "all services are online" since February 2024
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; https://status.stripe.com/current
&lt;span class="go"&gt;{"statuses":{"api":"up","webhooks":"up",...},
 "largestatus":"up",
 "message":"All services are online.",
 "time":"February 09, 2024 @ 06:08PM +00:00"}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;HTTP 200. Well-formed JSON. Reassuring message. And a timestamp from over two years ago that has not moved since. I re-ran that curl the morning I published this, and it still says exactly that.&lt;/p&gt;

&lt;p&gt;Stripe's human status page is fine. They migrated, and the new one works. The old JSON endpoint was simply never turned off, so it still answers, still says everything is up, and will keep saying that through any incident you care about. If you wired a dashboard to it in 2023, it is still green today and it means nothing.&lt;/p&gt;

&lt;p&gt;This is the single strongest argument I know of for not trusting a status endpoint you haven't checked the freshness of. It's also why I refuse to list Stripe at all rather than serve a fossil. A green light that cannot turn red is worse than no light.&lt;/p&gt;

&lt;h2&gt;
  
  
  Vendors forget to close incidents
&lt;/h2&gt;

&lt;p&gt;At the time of writing, AWS still lists two open events in its own health feed, one in me-central-1 and one in me-south-1, opened on 1 and 2 March. That is over 3,700 hours each, about 157 days. Narrow the question to incidents that opened in the last 30 days and the longest is a Telnyx incident at 506 hours, nearly 21 days, followed by a KnowBe4 purchasing page at 463 hours.&lt;/p&gt;

&lt;p&gt;I don't think these are month-long outages. I think they're incidents someone opened, fixed, and never went back to close. But there is no way to tell that from the outside, and the vendor's own page still says open, so any honest aggregator has to either report it as open or start silently overriding vendors about their own systems. I report it, and I label the duration "stayed open" rather than "downtime", because those are not the same claim.&lt;/p&gt;

&lt;h2&gt;
  
  
  The genuinely strange ones
&lt;/h2&gt;

&lt;p&gt;Cisco Duo publishes 847 components with 94 distinct names. &lt;code&gt;Core Authentication Service&lt;/code&gt; appears 80 times, once per deployment shard. If you build your lookup with a naive &lt;code&gt;new Map(components.map(c =&amp;gt; [c.name, c]))&lt;/code&gt;, last wins, and 79 shards reporting an outage get masked by one healthy one at the end of the array. You have to take the worst status across every occurrence.&lt;/p&gt;

&lt;p&gt;ClickHouse has a component named &lt;code&gt;AWS  us-west-2&lt;/code&gt;, with two spaces. Match on the exact string or you will never map it.&lt;/p&gt;

&lt;p&gt;NetSuite once published its internal telemetry as public incidents. Real entries, in the real feed, titled &lt;code&gt;_system_metadata:eyJ1cHRpbWUi…&lt;/code&gt;. Base64-decode that and you get &lt;code&gt;{"uptime":"99.99","requests_served":…}&lt;/code&gt;. Somebody's monitoring pipeline was writing to the customer-facing incident stream.&lt;/p&gt;

&lt;p&gt;Several status pages block non-browser clients. 8x8's WAF returns 403 to anything without a browser user-agent. Okta's status API returns 401. A status page that only a human can read is, for automation purposes, not a status page.&lt;/p&gt;

&lt;p&gt;No consumer carrier publishes one at all. Vodafone, AT&amp;amp;T, Verizon, T-Mobile, BT, Orange, Telstra: I checked all of them. There is no official machine-readable status feed for any major consumer telecom operator. Every site that appears to show you one is showing you crowd reports.&lt;/p&gt;

&lt;h2&gt;
  
  
  What a month of this actually looks like
&lt;/h2&gt;

&lt;p&gt;Across the last 30 days, the 172 providers logged 1,455 incidents between them, and 151 of the 172 had at least one. 369 were rated major or critical by the vendor themselves: 267 major, 102 critical, against 1,084 minor. Telecom and connectivity was the busiest category with 305, then cloud and infrastructure at 219, then developer tools at 196, then AI at 147.&lt;/p&gt;

&lt;p&gt;The distribution is the part I found most useful. Most of it is minor, and most of what a status page publishes is noise relative to your stack. The question that actually matters during an incident isn't "what's broken somewhere". It's "is anything I depend on broken, right now, according to the vendor itself".&lt;/p&gt;

&lt;h2&gt;
  
  
  The takeaway I'd want if I were reading this
&lt;/h2&gt;

&lt;p&gt;If you consume vendor status programmatically:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Check the timestamp, always. A stale-but-green endpoint is the failure mode you will not notice.&lt;/li&gt;
&lt;li&gt;Assume component names repeat. Aggregate to worst-status, never last-wins.&lt;/li&gt;
&lt;li&gt;Don't trust a compatible-looking payload. Assert that the fields you need exist.&lt;/li&gt;
&lt;li&gt;Decode by bytes, not by assumption. Check for a BOM before parsing.&lt;/li&gt;
&lt;li&gt;Treat "open" as "the vendor hasn't closed it", which is not the same as "still down".&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I turned all of this into &lt;a href="https://outagedeck.com" rel="noopener noreferrer"&gt;OutageDeck&lt;/a&gt;, which reads those 172 feeds every ten minutes so you don't have to write the decoders. But honestly, the five rules above are most of the value. If you're building this in-house, that's the list I wish I'd had.&lt;/p&gt;

&lt;p&gt;Happy to answer anything about specific feeds in the comments. If there's a vendor whose format has broken you in an interesting way, I'd like to hear it.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>sre</category>
      <category>api</category>
      <category>webdev</category>
    </item>
    <item>
      <title>There's no standard status page, and other lessons from tracking 96 providers</title>
      <dc:creator>Kerolos Atallah</dc:creator>
      <pubDate>Sat, 18 Jul 2026 01:50:09 +0000</pubDate>
      <link>https://dev.to/kerolos_atallah/theres-no-standard-status-page-and-other-lessons-from-tracking-96-providers-56k6</link>
      <guid>https://dev.to/kerolos_atallah/theres-no-standard-status-page-and-other-lessons-from-tracking-96-providers-56k6</guid>
      <description>&lt;p&gt;Your Slack won't load. Is it you, your VPN, the office wifi, or Slack? You open Slack's status page and it's green. It's often green while you're clearly down, because a company updates its own status page &lt;em&gt;after&lt;/em&gt; it confirms an incident — not the moment you feel it.&lt;/p&gt;

&lt;p&gt;I spent the last few months building &lt;a href="https://outagedeck.com" rel="noopener noreferrer"&gt;OutageDeck&lt;/a&gt;, which reads the official status source of 96 cloud and SaaS providers and folds them into one place. I assumed the hard part would be the frontend. It wasn't. The hard part was that "official status" is a swamp. Here's what I found in it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The short version:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;There is no standard status format. Statuspage is common, but the tail is bespoke — Google, Slack, Heroku, Azure over RSS, and AWS in UTF-16.&lt;/li&gt;
&lt;li&gt;Providers' own timestamps lag, sometimes by days, so you can't compute uptime from them.&lt;/li&gt;
&lt;li&gt;Some official feeds are stale fossils, or model thousands of instances, so "is it up?" has no single answer.&lt;/li&gt;
&lt;li&gt;Official status is authoritative but late — which is the whole reason crowd-sourced "is it down?" sites exist.&lt;/li&gt;
&lt;li&gt;All of this pushed me toward a deliberately tiny backend: one Next.js app and a Postgres database, no queue, about $55/month.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  There is no standard
&lt;/h2&gt;

&lt;p&gt;Atlassian Statuspage is the closest thing to a common language. Around 89 of my 96 providers expose a Statuspage-style &lt;code&gt;summary.json&lt;/code&gt; and &lt;code&gt;incidents.json&lt;/code&gt;, and one adapter reads all of them. Some providers don't even run Statuspage but copy its shape anyway — incident.io serves a Statuspage-compatible endpoint on each customer's own domain, so Notion and Linear parse with the exact same code.&lt;/p&gt;

&lt;p&gt;Then the long tail starts. Google publishes an &lt;code&gt;incidents.json&lt;/code&gt; in its own format (shared across Cloud, Workspace, and Firebase). Slack has a bespoke API. Heroku is on the fourth version of its own. Azure only offers RSS. AWS ships an event feed encoded in &lt;strong&gt;UTF-16 with a byte-order mark&lt;/strong&gt;, which silently breaks any parser that assumes UTF-8. "Just read the status page" turned into six adapters and a pile of encoding checks.&lt;/p&gt;

&lt;h2&gt;
  
  
  The timestamps lie
&lt;/h2&gt;

&lt;p&gt;My first uptime numbers were nonsense, and it took me a while to see why: I was computing them from each provider's own &lt;code&gt;captured_at&lt;/code&gt; timestamp, and those lag. One provider's was &lt;strong&gt;days&lt;/strong&gt; behind at one point. If a feed says a state was "captured three days ago," you can't tell whether the service was down for three days or the timestamp is just stale.&lt;/p&gt;

&lt;p&gt;The fix was to stop trusting upstream time entirely. Every observation is stamped with &lt;em&gt;my&lt;/em&gt; check time, and uptime is computed from when I saw a state, not when the provider says it happened. The corollary matters too: if my own poller has a gap — a deploy, say — I don't backfill it as "up." Any gap longer than 30 minutes is recorded as &lt;em&gt;no data&lt;/em&gt;, because inventing green is worse than admitting I wasn't looking.&lt;/p&gt;

&lt;h2&gt;
  
  
  Some official sources are fossils
&lt;/h2&gt;

&lt;p&gt;A few providers technically have a machine-readable status endpoint that you still can't use. Stripe's legacy status JSON has been effectively frozen since 2024; it will cheerfully report that everything is fine, forever. Salesforce's status API models nearly 3,900 separate instances, so "is Salesforce up?" depends entirely on which pod your org sits on.&lt;/p&gt;

&lt;p&gt;For sources like these, the honest move is to &lt;em&gt;not&lt;/em&gt; ship them until I have something I'd trust myself. That's why they're still missing from the list. I'd rather explain a gap than fake a green light.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the feeds did to the backend
&lt;/h2&gt;

&lt;p&gt;Two properties of these feeds shaped the whole system.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;They re-send their full recent history on every poll,&lt;/strong&gt; and an unchanged upstream just re-stamps the same row. So the raw data can't reconstruct history — you can't diff yesterday back out of it. Instead of trying to rederive it later, I roll each poll's observations into daily per-provider buckets at write time. I also skip writing rows that didn't change; an early version rewrote identical rows every run and burned the database's IO budget for nothing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I run two schedulers on purpose:&lt;/strong&gt; a 10-minute cron as the primary, and a 30-minute job as a backstop. So runs overlap. Rather than add a queue or a lock service, I let Postgres be the referee. Alert deliveries are claimed with a unique constraint before anything goes out:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- alert_deliveries has: unique (subscription_id, event_key)&lt;/span&gt;
&lt;span class="k"&gt;insert&lt;/span&gt; &lt;span class="k"&gt;into&lt;/span&gt; &lt;span class="n"&gt;alert_deliveries&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;subscription_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;event_key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;values&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;on&lt;/span&gt; &lt;span class="n"&gt;conflict&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;subscription_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;event_key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="k"&gt;nothing&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;-- 1 row inserted  -&amp;gt; I won the claim, send the alert&lt;/span&gt;
&lt;span class="c1"&gt;-- 0 rows inserted -&amp;gt; another run already has it, skip&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The insert that survives the unique index is the one that sends; the overlapping run writes nothing and moves on. No queue, no exactly-once framework, no dead-letter topic. The uptime writes take a per-entity advisory lock for the same reason. The whole thing is one Next.js app and a Postgres database, no background workers, running on about &lt;strong&gt;$55 a month&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  So I built the thing I wanted
&lt;/h2&gt;

&lt;p&gt;OutageDeck is the result: one place to check whether 96 major providers are up, sourced from each one's official status feed rather than from user complaints. It's free to use and there's no signup to check a provider. Under the hood it's the pipeline above — official-only, honest about timestamps, and clear when it just doesn't know yet.&lt;/p&gt;

&lt;p&gt;If you want more than a webpage, there's a public JSON API, embeddable SVG status badges you can drop in a README, RSS feeds per provider, and an OpenAPI 3.1 doc.&lt;/p&gt;

&lt;p&gt;Two honest caveats: incident history only goes as deep as each upstream feed exposes, so this isn't a system of record for ancient outages; and I'm still adding providers as I find sources I actually trust.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it, and stay in the loop
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Check any provider, free, no signup:&lt;/strong&gt; &lt;a href="https://outagedeck.com" rel="noopener noreferrer"&gt;outagedeck.com&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Want a heads-up when something breaks?&lt;/strong&gt; Free email alerts for up to 5 providers; paid plans add Slack, Discord, and webhooks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prefer a digest?&lt;/strong&gt; I send a short weekly rundown, &lt;em&gt;This week in cloud outages&lt;/em&gt; — you can subscribe on the site.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I'd genuinely like to know two things in the comments: &lt;strong&gt;which providers you'd want tracked next&lt;/strong&gt;, and &lt;strong&gt;what would make the API useful inside your own monitoring&lt;/strong&gt;. I'll be writing up more of the internals (the uptime rollups, the fail-open API) — follow along if that's your thing.&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>devops</category>
      <category>postgres</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
