<?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: Nikola</title>
    <description>The latest articles on DEV Community by Nikola (@dragstor).</description>
    <link>https://dev.to/dragstor</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%2F170737%2F4e18e019-e796-4e01-b795-019f3f77348f.jpg</url>
      <title>DEV Community: Nikola</title>
      <link>https://dev.to/dragstor</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/dragstor"/>
    <language>en</language>
    <item>
      <title>I Built a Server Agent Because Uptime Checks Tell You What Failed, Not Why</title>
      <dc:creator>Nikola</dc:creator>
      <pubDate>Tue, 04 Aug 2026 21:14:20 +0000</pubDate>
      <link>https://dev.to/dragstor/i-built-a-server-agent-because-uptime-checks-tell-you-what-failed-not-why-20hn</link>
      <guid>https://dev.to/dragstor/i-built-a-server-agent-because-uptime-checks-tell-you-what-failed-not-why-20hn</guid>
      <description>&lt;p&gt;A status page has a blind spot.&lt;/p&gt;

&lt;p&gt;It can tell you that your API is returning 502s. It can tell you that a TCP port stopped accepting connections. It can tell you when the incident started.&lt;/p&gt;

&lt;p&gt;It usually cannot tell you &lt;em&gt;why&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Was the application host out of memory? Was disk I/O saturated? Did load climb for 40 minutes before users noticed? Was the server completely healthy and the real problem somewhere else?&lt;/p&gt;

&lt;p&gt;Those answers often live in a separate monitoring product, disconnected from the incident timeline and disconnected from the status page.&lt;/p&gt;

&lt;p&gt;That is why I built &lt;strong&gt;Servers&lt;/strong&gt; for &lt;a href="https://statuspage.me/?utm_source=dev.to&amp;amp;utm_medium=community&amp;amp;utm_campaign=servers&amp;amp;utm_content=server-agent-post"&gt;StatusPage.me&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It is a small, customer-installed host metrics agent and dashboard. You install it on a machine you operate, and it reports CPU, memory, swap, load, disk, and network metrics back to your account.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqa343sumxyz1xg9k680e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqa343sumxyz1xg9k680e.png" alt=" " width="800" height="638"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The important part is not “now there are more graphs.”&lt;/p&gt;

&lt;p&gt;The important part is seeing an outage and the host evidence around it on the same timeline.&lt;/p&gt;

&lt;h2&gt;
  
  
  External checks answer one question. Host metrics answer another.
&lt;/h2&gt;

&lt;p&gt;Regular uptime monitoring is still the right tool for the outside-in view:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Can users reach the website?&lt;/li&gt;
&lt;li&gt;Is the API returning the expected response?&lt;/li&gt;
&lt;li&gt;Does DNS resolve correctly?&lt;/li&gt;
&lt;li&gt;Is the database port open?&lt;/li&gt;
&lt;li&gt;Did a scheduled job run?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But those checks do not run inside your infrastructure.&lt;/p&gt;

&lt;p&gt;A healthy HTTP response does not prove that a background worker is about to run out of memory. A timeout does not prove that the app server is overloaded. And an incident can start with a slow disk or growing swap usage long before an endpoint is fully unavailable.&lt;/p&gt;

&lt;p&gt;The distinction is simple:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;External monitoring tells you what users can see.&lt;br&gt;&lt;br&gt;
Host metrics help explain what the machine was doing when they saw it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You need both.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Servers includes
&lt;/h2&gt;

&lt;p&gt;Each registered host gets a dedicated dashboard page with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CPU user, system, and I/O wait utilization&lt;/li&gt;
&lt;li&gt;Memory use&lt;/li&gt;
&lt;li&gt;Swap use&lt;/li&gt;
&lt;li&gt;Load averages&lt;/li&gt;
&lt;li&gt;Disk use and read/write throughput&lt;/li&gt;
&lt;li&gt;Network inbound and outbound throughput&lt;/li&gt;
&lt;li&gt;A human-readable OS description for account owners&lt;/li&gt;
&lt;li&gt;Current values, historical charts, one-hour change, and small trend sparklines&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The dashboard has views from one hour to 30 days, subject to your plan’s retention.&lt;/p&gt;

&lt;p&gt;There is also a practical detail that matters during a real incident: if the server is linked to a StatusPage.me status page, the incident windows are shaded directly on its charts.&lt;/p&gt;

&lt;p&gt;That lets you answer questions like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Did memory climb before the API went down?&lt;/li&gt;
&lt;li&gt;Did the load spike end when the incident was resolved?&lt;/li&gt;
&lt;li&gt;Was the host normal while the dependency failed?&lt;/li&gt;
&lt;li&gt;Is this a recurring pattern or a one-off event?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is more useful than opening four dashboards, trying to align timestamps, and guessing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Threshold alerts without alerting on every spike
&lt;/h2&gt;

&lt;p&gt;Servers also supports threshold rules on plans that include Server Agent alerts.&lt;/p&gt;

&lt;p&gt;You can alert on metrics such as CPU, memory, swap, load, disk, disk I/O, and network throughput. More importantly, you choose how long a condition must hold before it fires.&lt;/p&gt;

&lt;p&gt;That duration is deliberate.&lt;/p&gt;

&lt;p&gt;A brief CPU spike during a deploy should not wake someone up. Sustained resource pressure probably should.&lt;/p&gt;

&lt;p&gt;The goal is not to turn every graph into another noisy alert source. It is to catch the conditions that are likely to become an incident before they do.&lt;/p&gt;

&lt;h2&gt;
  
  
  The agent is open source because it runs on your production machines
&lt;/h2&gt;

&lt;p&gt;Asking someone to install an agent on a production server is a trust request.&lt;/p&gt;

&lt;p&gt;“Trust us” is not a sufficient answer.&lt;/p&gt;

&lt;p&gt;The Server Agent is open source:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/hosted-status-page/hsp-server-agent" rel="noopener noreferrer"&gt;https://github.com/hosted-status-page/hsp-server-agent&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can read the installer, the collector, the protocol, and the privacy documentation before installing anything.&lt;/p&gt;

&lt;p&gt;The dashboard generates a one-time installation command for each server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://statuspage.me/install-server-agent.sh | &lt;span class="nb"&gt;sudo &lt;/span&gt;bash &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--server-id&lt;/span&gt; &amp;lt;server-id&amp;gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--ingest-key&lt;/span&gt; &amp;lt;ingest-key&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should read a script before piping it into &lt;code&gt;sudo bash&lt;/code&gt;. That is true here, and it is true everywhere.&lt;/p&gt;

&lt;p&gt;The installer verifies the downloaded binary against a published SHA-256 checksum. It then installs the agent as a dedicated non-login system user, rather than leaving a root process running indefinitely.&lt;/p&gt;

&lt;p&gt;The resulting systemd service is deliberately restricted:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No new privileges&lt;/li&gt;
&lt;li&gt;No Linux capabilities&lt;/li&gt;
&lt;li&gt;Read-only filesystem access except for its own local buffer&lt;/li&gt;
&lt;li&gt;Private temporary directory and devices&lt;/li&gt;
&lt;li&gt;Restricted system calls&lt;/li&gt;
&lt;li&gt;Memory and CPU limits&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The agent needs to read system counters. It does not need to be a foothold on your host.&lt;/p&gt;

&lt;h2&gt;
  
  
  What data it collects
&lt;/h2&gt;

&lt;p&gt;By default, the agent collects one sample every 60 seconds and sends it outbound over HTTPS.&lt;/p&gt;

&lt;p&gt;A sample contains operational counters:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CPU percentages&lt;/li&gt;
&lt;li&gt;Memory and swap usage&lt;/li&gt;
&lt;li&gt;Load averages&lt;/li&gt;
&lt;li&gt;Disk capacity and I/O throughput&lt;/li&gt;
&lt;li&gt;Network throughput&lt;/li&gt;
&lt;li&gt;Uptime&lt;/li&gt;
&lt;li&gt;Optional per-filesystem and per-interface breakdowns&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It can also report an operating-system description and an optional hostname.&lt;/p&gt;

&lt;p&gt;The hostname is optional because hostnames often contain a person’s name, internal project name, or other information you may not want to retain. You can send no hostname at all, and you can edit or clear it from the dashboard later.&lt;/p&gt;

&lt;p&gt;Authentication is per server. The agent sends a server ID and ingest key in request headers, not in the URL. On the server side, the ingest key is stored as a one-way hash rather than plaintext.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it explicitly does &lt;em&gt;not&lt;/em&gt; collect
&lt;/h2&gt;

&lt;p&gt;This is the more important list.&lt;/p&gt;

&lt;p&gt;The agent does not collect:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Process names or process lists&lt;/li&gt;
&lt;li&gt;Command lines&lt;/li&gt;
&lt;li&gt;Environment variables&lt;/li&gt;
&lt;li&gt;File contents&lt;/li&gt;
&lt;li&gt;User accounts&lt;/li&gt;
&lt;li&gt;Network peers&lt;/li&gt;
&lt;li&gt;Raw client IP addresses&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is not just a policy statement. The wire protocol has a fixed schema. The ingest service rejects unknown fields instead of accepting arbitrary JSON and hoping it is harmless.&lt;/p&gt;

&lt;p&gt;There is no generic “metadata” bucket where process arguments, secrets, or application data can quietly end up later.&lt;/p&gt;

&lt;p&gt;You can inspect exactly what a host would send before configuring anything:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;serveragent &lt;span class="nt"&gt;-metrics&lt;/span&gt;
serveragent &lt;span class="nt"&gt;-dry-run&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first prints the collection policy. The second prints a real sample from the machine.&lt;/p&gt;

&lt;h2&gt;
  
  
  What happens when StatusPage.me is unreachable?
&lt;/h2&gt;

&lt;p&gt;A monitoring agent that fills the disk during an outage is worse than useless.&lt;/p&gt;

&lt;p&gt;If the endpoint is unreachable, the agent keeps collecting metrics and stores unsent samples locally. When connectivity returns, it flushes them oldest-first.&lt;/p&gt;

&lt;p&gt;The buffer is bounded: by default, it holds up to 2,880 samples, or roughly 48 hours at the default cadence. At the limit, the oldest samples are discarded.&lt;/p&gt;

&lt;p&gt;That tradeoff is intentional.&lt;/p&gt;

&lt;p&gt;Losing old telemetry after a prolonged communication outage is better than turning the monitored host into the outage by consuming its disk. Samples are removed from the local buffer only after the server confirms they were stored, and ingestion is idempotent so retries do not create duplicates.&lt;/p&gt;

&lt;p&gt;On the server side, raw metrics are stored in time-partitioned tables, then rolled up for longer retention according to the account’s plan.&lt;/p&gt;

&lt;p&gt;Deleting a server removes its stored metrics. Uninstalling the agent removes its binary, configuration, service account, and local buffer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Public infrastructure health, without publishing your infrastructure
&lt;/h2&gt;

&lt;p&gt;Some teams want to show customers more than “all systems operational.”&lt;/p&gt;

&lt;p&gt;That is reasonable. But publishing a server name, hostname, IP address, or exact disk capacity is not.&lt;/p&gt;

&lt;p&gt;Servers can optionally expose a small &lt;strong&gt;Infrastructure&lt;/strong&gt; section on a public status page when a host is linked to a component and the plan allows it.&lt;/p&gt;

&lt;p&gt;What is shown:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The component name&lt;/li&gt;
&lt;li&gt;CPU percentage&lt;/li&gt;
&lt;li&gt;Memory percentage&lt;/li&gt;
&lt;li&gt;Disk percentage&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What is never shown:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The server’s name&lt;/li&gt;
&lt;li&gt;Hostname&lt;/li&gt;
&lt;li&gt;IP address&lt;/li&gt;
&lt;li&gt;Operating-system details&lt;/li&gt;
&lt;li&gt;Absolute byte counts&lt;/li&gt;
&lt;li&gt;Internal capacity&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If the host stops reporting, it disappears from the public view instead of showing stale data.&lt;/p&gt;

&lt;p&gt;That is the boundary: show a useful operational signal, not an infrastructure inventory.&lt;/p&gt;

&lt;h2&gt;
  
  
  This is not trying to replace every observability tool
&lt;/h2&gt;

&lt;p&gt;Servers is not a log platform. It is not distributed tracing. It is not a process profiler. It does not pretend to be a full observability suite.&lt;/p&gt;

&lt;p&gt;It is intentionally narrow.&lt;/p&gt;

&lt;p&gt;The job is to connect the status page, the incident timeline, and the host-level signals that help explain an outage.&lt;/p&gt;

&lt;p&gt;If an API fails while memory climbs steadily, that should be obvious. If the host is healthy, that should be obvious too.&lt;/p&gt;

&lt;p&gt;The product is available now in StatusPage.me. The source for the agent is here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/hosted-status-page/hsp-server-agent" rel="noopener noreferrer"&gt;https://github.com/hosted-status-page/hsp-server-agent&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And the full setup guide is here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://statuspage.me/docs/servers/servers-monitoring" rel="noopener noreferrer"&gt;https://statuspage.me/docs/servers/servers-monitoring&lt;/a&gt;&lt;/p&gt;

</description>
      <category>devops</category>
      <category>monitoring</category>
      <category>opensource</category>
      <category>selfhosted</category>
    </item>
    <item>
      <title>I Switched Domains Based on ChatGPT's Advice and Lost All My Google Rankings (4 Month Migration Case Study)</title>
      <dc:creator>Nikola</dc:creator>
      <pubDate>Fri, 13 Feb 2026 23:29:21 +0000</pubDate>
      <link>https://dev.to/dragstor/i-switched-domains-based-on-chatgpts-advice-and-lost-all-my-google-rankings-4-month-migration-4dip</link>
      <guid>https://dev.to/dragstor/i-switched-domains-based-on-chatgpts-advice-and-lost-all-my-google-rankings-4-month-migration-4dip</guid>
      <description>&lt;p&gt;In late 2025, I revived a project I'd put on hold for years.&lt;/p&gt;

&lt;p&gt;I had two domains:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;hostedstatus.page&lt;/strong&gt; - Ranking #1-3 for "hosted status page" on all search engines&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;statuspage.me&lt;/strong&gt; - Sitting unused since 2018&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I asked ChatGPT: &lt;em&gt;"Which domain should I use?"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;ChatGPT said: &lt;em&gt;"statuspage.me is catchier and more memorable. Switch to it."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I trusted the AI.&lt;/p&gt;

&lt;p&gt;I did a proper domain migration:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;301 redirects from hostedstatus.page → statuspage.me&lt;/li&gt;
&lt;li&gt;Google Search Console domain change notification&lt;/li&gt;
&lt;li&gt;Bing Webmaster Tools migration&lt;/li&gt;
&lt;li&gt;Yandex domain change&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Everything by the book.&lt;/p&gt;

&lt;p&gt;Four months later:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Google:&lt;/strong&gt; Invisible (page 10+)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DuckDuckGo:&lt;/strong&gt; Page 1, position #3&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bing:&lt;/strong&gt; Multiple page 1 rankings&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ChatGPT:&lt;/strong&gt; Citing my content&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here's what actually happened when I migrated domains — and why different search engines behave so differently.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Setup
&lt;/h2&gt;

&lt;p&gt;I've been building &lt;a href="https://statuspage.me" rel="noopener noreferrer"&gt;StatusPage.me&lt;/a&gt; - a status page and monitoring service for indie hackers, SMBs, SaaS companies, etc. The product differentiates through indie-first pricing, an OSS Hero program (free for open source projects), and affordable pricing.&lt;/p&gt;

&lt;p&gt;Back in ~2018, I registered both domains:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;hostedstatus.page&lt;/strong&gt; - Self-documenting, clear value prop&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;statuspage.me&lt;/strong&gt; - Shorter, snappier, competing with statuspage.io&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I built the initial version on hostedstatus.page, but the product went on hold due to an employment contract with an IP clause. During those years, hostedstatus.page sat there, accumulating some organic search authority.&lt;/p&gt;

&lt;p&gt;In 2025, I left that job and revived the project. I immediately decided to migrate to statuspage.me and asked ChatGPT for confirmation.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Decision
&lt;/h2&gt;

&lt;p&gt;ChatGPT's reasoning seemed solid:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"statuspage.me is catchier, more memorable, and easier to say. It competes directly with statuspage.io in people's minds. The shorter domain is better for branding."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This felt right. &lt;strong&gt;hostedstatus.page&lt;/strong&gt; was wordy and defensive. &lt;strong&gt;statuspage.me&lt;/strong&gt; was confident and clean.&lt;/p&gt;

&lt;p&gt;What I didn't consider: I was asking for &lt;strong&gt;branding advice&lt;/strong&gt;, not &lt;strong&gt;SEO advice&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For a bootstrap SaaS dependent on organic traffic, that's a critical distinction.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Migration (Done Right)
&lt;/h2&gt;

&lt;p&gt;I did everything correctly:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;301 redirects&lt;/strong&gt; from every hostedstatus.page URL → statuspage.me equivalent&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Google Search Console&lt;/strong&gt; "Change of address" tool&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bing Webmaster Tools&lt;/strong&gt; domain migration notification
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Yandex&lt;/strong&gt; domain change submission&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Updated all backlinks&lt;/strong&gt; I had control over&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is textbook domain migration. Every SEO guide says this is how you do it.&lt;/p&gt;

&lt;p&gt;And it worked... sort of.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Crash (Google)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Google rankings before migration:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"hosted status page": Position #1-3&lt;/li&gt;
&lt;li&gt;"status page": Lower first page / page 2&lt;/li&gt;
&lt;li&gt;Clean organic traffic from search&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Google rankings 4 months after migration:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"hosted status page": Page 10+ (invisible)&lt;/li&gt;
&lt;li&gt;"status page": Page 10+ (invisible)&lt;/li&gt;
&lt;li&gt;Organic traffic: Significantly reduced&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Google Search Console showed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;⚠️ "This site is currently moving to statuspage.me"&lt;/li&gt;
&lt;li&gt;✅ Pages being indexed (621 indexed pages)&lt;/li&gt;
&lt;li&gt;❌ Link data: "No data" (authority not yet transferred)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The migration was &lt;strong&gt;recognized&lt;/strong&gt; but not &lt;strong&gt;processed&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Plot Twist
&lt;/h2&gt;

&lt;p&gt;After sharing my story on X, my wife suggested I check other search engines.&lt;/p&gt;

&lt;p&gt;I had been so focused on Google that I hadn't looked elsewhere.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DuckDuckGo results:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Searching "status page":&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Position #3:&lt;/strong&gt; My blog post "What Is a Status Page? The 2026 Practical Guide"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Searching "statuspage":  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Position #3:&lt;/strong&gt; StatusPage.me homepage&lt;/li&gt;
&lt;li&gt;Beating Status.io, Better Stack, StatusGator&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Bing results:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Searching "statuspage":&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Multiple page 1 listings&lt;/strong&gt; for statuspage.me&lt;/li&gt;
&lt;li&gt;Blog post + homepage both ranking&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;ChatGPT search:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When people ask ChatGPT about status pages, it &lt;strong&gt;cites my blog post&lt;/strong&gt; as a reference source.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Google results:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Searching "status page":&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Invisible. Page 10+.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  What I Learned: Different Engines, Different Timelines
&lt;/h2&gt;

&lt;p&gt;Domain migrations don't happen uniformly across search engines.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DuckDuckGo / Bing:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Processed the 301 redirects in &lt;strong&gt;2-4 weeks&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Transferred most link equity quickly&lt;/li&gt;
&lt;li&gt;Content quality weighted heavily&lt;/li&gt;
&lt;li&gt;Freshness and relevance prioritized&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Google:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Takes &lt;strong&gt;6-12 months&lt;/strong&gt; to fully transfer authority&lt;/li&gt;
&lt;li&gt;More conservative about domain migrations (anti-manipulation)&lt;/li&gt;
&lt;li&gt;Heavier emphasis on domain age and backlink history&lt;/li&gt;
&lt;li&gt;Competitive keywords get extra scrutiny&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The technical migration was done correctly. The difference is &lt;strong&gt;algorithmic philosophy&lt;/strong&gt;, not execution.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Google Is Slower
&lt;/h2&gt;

&lt;p&gt;Google's caution makes sense from their perspective:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Domain migrations can be gamed&lt;/strong&gt; - Buying aged domains to inherit authority&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Competitive keywords = higher scrutiny&lt;/strong&gt; - "status page" is a commercial keyword&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Authority takes time to validate&lt;/strong&gt; - Google wants proof the new domain deserves the old rankings&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Link graph recalculation is expensive&lt;/strong&gt; - Backlinks need to be revalidated&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Bing and DuckDuckGo recovered faster because they weight &lt;strong&gt;content quality&lt;/strong&gt; and &lt;strong&gt;freshness&lt;/strong&gt; more heavily than &lt;strong&gt;domain authority history&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Data Backs This Up
&lt;/h2&gt;

&lt;p&gt;My domain metrics:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Domain Rating:&lt;/strong&gt; 36/100 (respectable)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Referring Domains:&lt;/strong&gt; 72&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Domain Age:&lt;/strong&gt; 6 years, 11 months (registered 2018, but unused until late 2025)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The backlinks exist. Google just hasn't &lt;strong&gt;credited&lt;/strong&gt; them yet.&lt;/p&gt;

&lt;p&gt;Meanwhile, DuckDuckGo and Bing saw the 301s, validated the content, and moved on.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Didn't Work: The Directory Submission Grind
&lt;/h2&gt;

&lt;p&gt;I'll be honest about something that wasted time: directory submissions.&lt;/p&gt;

&lt;p&gt;After the migration, I submitted statuspage.me to dozens of directories. The metrics looked promising:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Domain Rating climbed from 1 → 36&lt;/li&gt;
&lt;li&gt;Referring domains grew from 1 → 72&lt;/li&gt;
&lt;li&gt;Backlink count hit 1,668&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The result?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Organic traffic: 0 (until Jan 2026, then 1 visit/month)&lt;/li&gt;
&lt;li&gt;Google rankings: Still page 10+&lt;/li&gt;
&lt;li&gt;Actual conversions: 0&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Directory links are &lt;strong&gt;vanity metrics&lt;/strong&gt;. They raise your DR number, but most directories have little to no authority themselves. Google doesn't value them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What actually drove results:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Quality blog content on dev.to&lt;/li&gt;
&lt;li&gt;DuckDuckGo/Bing ranking my actual helpful content&lt;/li&gt;
&lt;li&gt;ChatGPT citing my blog post&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The lesson:&lt;/strong&gt; One well-written, genuinely useful blog post &amp;gt; 50 directory submissions.&lt;/p&gt;




&lt;h2&gt;
  
  
  Was It A Mistake?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Short answer: No, but with caveats.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What I got right:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;statuspage.me &lt;strong&gt;is&lt;/strong&gt; a better brand name&lt;/li&gt;
&lt;li&gt;Technical migration was done correctly&lt;/li&gt;
&lt;li&gt;Content quality maintained&lt;/li&gt;
&lt;li&gt;Long-term positioning improved&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What I got wrong:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Underestimated Google's migration timeline&lt;/li&gt;
&lt;li&gt;Didn't check other search engines sooner (would've panicked less)&lt;/li&gt;
&lt;li&gt;Wasted time on directory submissions&lt;/li&gt;
&lt;li&gt;Didn't consider that "better branding" has a 6-12 month SEO tax&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The real lesson:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;ChatGPT gave me branding advice when I needed &lt;strong&gt;SEO + business context&lt;/strong&gt; advice.&lt;/p&gt;

&lt;p&gt;For a bootstrap SaaS dependent on organic traffic, &lt;strong&gt;throwing away established rankings has a cost&lt;/strong&gt; — even when done correctly.&lt;/p&gt;

&lt;p&gt;The question I should have asked: &lt;em&gt;"Can I afford 6-12 months of reduced Google traffic?"&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;AI Search Engines - The Mixed Results:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Perplexity.ai:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fecidhh6faro6rqsw5pfp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fecidhh6faro6rqsw5pfp.png" alt="Perplexity showing statuspage.me in " width="800" height="839"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When asked about status pages, Perplexity listed statuspage.me alongside Status.io, Atlassian Statuspage, and UptimeRobot, highlighting "Multi-region checks, OSS-friendly."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ChatGPT:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Cites my blog post "What Is a Status Page?" when people search for status page information.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Gemini (Google's AI):&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When I explicitly asked about statuspage.me, Gemini provided detailed analysis, seamingly from an outdated site.&lt;/p&gt;

&lt;p&gt;But notably: When asked for general recommendations, Gemini suggested Better Stack, UptimeRobot, and Instatus - not statuspage.me.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The takeaway:&lt;/strong&gt; AI search engines are discovering statuspage.me (Perplexity, ChatGPT), but Google's own AI (Gemini) still defaults to more established brands. The same pattern as Google Search itself.&lt;/p&gt;




&lt;h2&gt;
  
  
  What This Means For You
&lt;/h2&gt;

&lt;h3&gt;
  
  
  If you're considering a domain migration:
&lt;/h3&gt;

&lt;p&gt;✅ &lt;strong&gt;Do migrate if:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You have multiple traffic sources (not just SEO)&lt;/li&gt;
&lt;li&gt;The new domain is significantly better for branding&lt;/li&gt;
&lt;li&gt;You can afford 6-12 months of reduced Google traffic&lt;/li&gt;
&lt;li&gt;You're patient and have runway&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;❌ &lt;strong&gt;Don't migrate if:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Google organic is your primary traffic source&lt;/li&gt;
&lt;li&gt;You're pre-launch or early stage&lt;/li&gt;
&lt;li&gt;You need immediate results&lt;/li&gt;
&lt;li&gt;Current domain is performing well&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  If you're in the middle of a migration:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Don't panic if Google rankings drop&lt;/li&gt;
&lt;li&gt;Check Bing/DuckDuckGo - they recover faster&lt;/li&gt;
&lt;li&gt;Monitor Google Search Console for migration status&lt;/li&gt;
&lt;li&gt;Keep 301 redirects in place for at least 12 months&lt;/li&gt;
&lt;li&gt;Continue publishing quality content&lt;/li&gt;
&lt;li&gt;Skip the directory submissions - focus on real content&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  What I'm Doing Now (4 Months In)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;The current state:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;DuckDuckGo: Page 1 rankings ✅&lt;/li&gt;
&lt;li&gt;Bing: Page 1 rankings ✅
&lt;/li&gt;
&lt;li&gt;ChatGPT: Content being cited ✅&lt;/li&gt;
&lt;li&gt;Google: Slowly climbing back ⏳&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvzpp30fdar7w6r5bg2ug.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvzpp30fdar7w6r5bg2ug.png" alt="Bing citing statuspage.me" width="800" height="491"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Example links:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://duckduckgo.com/?q=statuspage&amp;amp;t=h_&amp;amp;ia=web" rel="noopener noreferrer"&gt;https://duckduckgo.com/?q=statuspage&amp;amp;t=h_&amp;amp;ia=web&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://duckduckgo.com/?q=status+page&amp;amp;t=h_&amp;amp;ia=web" rel="noopener noreferrer"&gt;https://duckduckgo.com/?q=status+page&amp;amp;t=h_&amp;amp;ia=web&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.bing.com/search?q=statuspage" rel="noopener noreferrer"&gt;https://www.bing.com/search?q=statuspage&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.bing.com/search?q=status+page" rel="noopener noreferrer"&gt;https://www.bing.com/search?q=status+page&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://yandex.com/search/?text=status+page" rel="noopener noreferrer"&gt;https://yandex.com/search/?text=status+page&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcxb4t4glktrrbbb0yh3o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcxb4t4glktrrbbb0yh3o.png" alt="DuckDuckGo - position 3 for " width="800" height="839"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Active strategies:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Building in public on X (&lt;a href="https://x.com/IT_mafija" rel="noopener noreferrer"&gt;@IT_mafija&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Writing technical content on dev.to (&lt;a href="https://dev.to/dragstor/why-a-status-page-should-not-depend-on-third-party-cdns-gk"&gt;previous&lt;/a&gt; &lt;a href="https://dev.to/dragstor/removing-third-party-dependencies-made-my-status-page-faster-heres-how-4a17"&gt;posts&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Direct outreach to indie hackers and OSS projects&lt;/li&gt;
&lt;li&gt;Long-tail SEO for less competitive keywords&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;IndexNow integration&lt;/strong&gt; - Auto-submitting new/modified pages&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;On the IndexNow implementation:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;About a month ago, I added IndexNow to my internal tooling. It detects new blog posts, docs, and page updates, then (with my approval) submits them to Bing, DuckDuckGo, and Yandex.&lt;/p&gt;

&lt;p&gt;Google doesn't support IndexNow - they rely on crawling and sitemaps.&lt;/p&gt;

&lt;p&gt;This gives Bing/DuckDuckGo a structural advantage: I can tell them immediately when content changes, rather than waiting for their next crawl.&lt;/p&gt;

&lt;p&gt;It's a small thing, but it compounds. Fresh content gets indexed in hours instead of days.&lt;/p&gt;




&lt;h2&gt;
  
  
  Practical Takeaways
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;For domain migrations:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Google takes 6-12 months - this is normal, even with perfect execution&lt;/li&gt;
&lt;li&gt;Bing/DuckDuckGo process migrations 10-20x faster&lt;/li&gt;
&lt;li&gt;Different search engines = different algorithmic priorities&lt;/li&gt;
&lt;li&gt;Check ALL search engines, not just Google&lt;/li&gt;
&lt;li&gt;IndexNow helps Bing/DDG (but Google doesn't support it)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;For bootstrap founders:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;"Better branding" has a real SEO cost&lt;/li&gt;
&lt;li&gt;Directory submissions are vanity metrics&lt;/li&gt;
&lt;li&gt;One quality blog post &amp;gt; 50 directory links&lt;/li&gt;
&lt;li&gt;Content that gets cited by ChatGPT = new distribution channel&lt;/li&gt;
&lt;li&gt;DuckDuckGo/Bing traffic is real (especially from tech-savvy users)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;For anyone asking AI for advice:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Specify your constraints (bootstrap, SEO-dependent, timeline)&lt;/li&gt;
&lt;li&gt;Ask for business context, not just branding advice&lt;/li&gt;
&lt;li&gt;AI doesn't understand your specific situation&lt;/li&gt;
&lt;li&gt;Get multiple perspectives before big decisions&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  The Uncomfortable Truth
&lt;/h2&gt;

&lt;p&gt;Most domain migration guides focus on technical execution.&lt;/p&gt;

&lt;p&gt;They assume all search engines behave the same way.&lt;/p&gt;

&lt;p&gt;They don't.&lt;/p&gt;

&lt;p&gt;Google's 6-12 month timeline is real, documented, and unavoidable - even when you do everything right.&lt;/p&gt;

&lt;p&gt;If you're dependent on Google traffic and can't afford that gap, the "better domain" might not be worth it.&lt;/p&gt;

&lt;p&gt;But if you can weather the storm, the long-term brand positioning might justify the short-term pain.&lt;/p&gt;

&lt;p&gt;I'm 4 months in. Ask me again in 12 months.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Building StatusPage.me - status pages + monitoring for indie hackers.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The domain migration journey continues. Follow along: &lt;a href="https://x.com/IT_mafija" rel="noopener noreferrer"&gt;@IT_mafija&lt;/a&gt; | &lt;a href="https://statuspage.me" rel="noopener noreferrer"&gt;statuspage.me&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>seo</category>
      <category>webdev</category>
      <category>startup</category>
      <category>buildinpublic</category>
    </item>
    <item>
      <title>Removing Third-Party Dependencies Made My Status Page Faster (Here’s How)</title>
      <dc:creator>Nikola</dc:creator>
      <pubDate>Wed, 11 Feb 2026 09:53:43 +0000</pubDate>
      <link>https://dev.to/dragstor/removing-third-party-dependencies-made-my-status-page-faster-heres-how-4a17</link>
      <guid>https://dev.to/dragstor/removing-third-party-dependencies-made-my-status-page-faster-heres-how-4a17</guid>
      <description>&lt;p&gt;When I wrote about &lt;a href="https://dev.to/dragstor/why-a-status-page-should-not-depend-on-third-party-cdns-gk"&gt;why a status page shouldn’t depend on third-party CDNs&lt;/a&gt;, the immediate response was predictable:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Sure, but CDNs are faster.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That assumption is so common it rarely gets tested. So I tested it.&lt;/p&gt;

&lt;p&gt;I removed all third-party runtime dependencies from my status pages.&lt;/p&gt;

&lt;p&gt;Nothing broke.&lt;/p&gt;

&lt;p&gt;Performance improved — materially.&lt;/p&gt;

&lt;p&gt;Not because of a trick, but because I removed architectural friction.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fewer requests&lt;/li&gt;
&lt;li&gt;Smaller payloads&lt;/li&gt;
&lt;li&gt;More predictable render behavior&lt;/li&gt;
&lt;li&gt;Lower TTFB&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To make this concrete:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Europe TTFB dropped from ~3s to ~181ms&lt;/li&gt;
&lt;li&gt;America dropped to ~530ms&lt;/li&gt;
&lt;li&gt;Asia Pacific dropped to ~861ms&lt;/li&gt;
&lt;li&gt;JavaScript bundle shrank from ~1MB to ~45KB&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Europe benefited the most because it’s closest to the primary infrastructure. Other regions are still bounded by geography.&lt;/p&gt;

&lt;p&gt;What changed wasn’t physics.&lt;br&gt;
It was server-side inefficiency.&lt;/p&gt;

&lt;p&gt;The architectural bottlenecks are gone.&lt;/p&gt;
&lt;h2&gt;
  
  
  What Didn't Change
&lt;/h2&gt;

&lt;p&gt;Geography still matters.&lt;/p&gt;

&lt;p&gt;Layered caching removes server-side bottlenecks.&lt;br&gt;
It does not remove physical distance.&lt;/p&gt;

&lt;p&gt;The goal wasn't to beat latency physics.&lt;br&gt;
It was to remove unnecessary self-inflicted delays.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This isn’t an anti-CDN rant.&lt;/strong&gt; CDNs are incredibly useful for many workloads. But a status page is not “many workloads.” It’s a very specific type of system with very specific goals.&lt;/p&gt;


&lt;h2&gt;
  
  
  What Comes Next
&lt;/h2&gt;

&lt;p&gt;Layered caching removed most self-inflicted latency.&lt;/p&gt;

&lt;p&gt;What remains is mostly geography.&lt;/p&gt;

&lt;p&gt;The next step is introducing read-only replicas in additional regions to reduce cross-region database round-trip time.&lt;/p&gt;

&lt;p&gt;Caching removes unnecessary work.&lt;br&gt;
Regional replicas reduce distance.&lt;/p&gt;

&lt;p&gt;They solve different problems.&lt;/p&gt;

&lt;p&gt;Layered caching made the system efficient.&lt;br&gt;
Replicas will make it geographically closer.&lt;/p&gt;

&lt;p&gt;They’re complementary, not interchangeable.&lt;/p&gt;


&lt;h2&gt;
  
  
  How I Actually Sped It Up
&lt;/h2&gt;

&lt;p&gt;There wasn’t one magic change. I removed a chain of small delays.&lt;/p&gt;

&lt;p&gt;The biggest wins came from:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Letting Caddy handle more of the boring HTTP work (compression + headers)&lt;/li&gt;
&lt;li&gt;Layered caching (browser → Redis → in-process → filesystem)&lt;/li&gt;
&lt;li&gt;Shrinking what the browser downloads and executes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The result wasn’t just better synthetic metrics. It felt faster.&lt;/p&gt;

&lt;p&gt;Before these changes, the cache hit rate was effectively 0% and the performance grade reflected that. After introducing layered caching and proper HTTP policies, repeated requests became dramatically cheaper.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftuulok56vu7vfwqremaw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftuulok56vu7vfwqremaw.png" alt="PageSpeed.dev test results for status.statuspage.me" width="800" height="631"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;a screenshot of &lt;a href="https://status.statuspage.me" rel="noopener noreferrer"&gt;https://status.statuspage.me&lt;/a&gt; test results&lt;/em&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  1. Caddy Tuning: Compression + Explicit Cache Policy
&lt;/h2&gt;

&lt;p&gt;Caddy is great out of the box. But status pages are perfect for aggressive HTTP fundamentals.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;example.com {
    encode zstd gzip

    # HTML: short-lived or revalidated
    @html path / /status* /incidents* /history*
    header @html Cache-Control "public, max-age=0, s-maxage=30, must-revalidate"

    # Fingerprinted assets: cache "forever"
    @assets path /assets/* /static/*
    header @assets Cache-Control "public, max-age=31536000, immutable"

    file_server
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Most of my pages behave like “mostly static + occasional updates.”&lt;/p&gt;

&lt;p&gt;So HTML is short-lived. Assets are immutable.&lt;/p&gt;

&lt;p&gt;That alone reduced repeat downloads to near-zero.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Static Files: Make Repeat Visits Cheap
&lt;/h2&gt;

&lt;p&gt;If fonts, icons, JS bundles, and CSS aren’t cached hard, you pay the same cost on every visit.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@fonts path /fonts/* /assets/fonts/*
header @fonts Cache-Control "public, max-age=31536000, immutable"

@images path /img/* /assets/img/*
header @images Cache-Control "public, max-age=604800"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Static delivery is the cheapest request your server can handle.&lt;br&gt;
Ideally it never reaches the app at all.&lt;/p&gt;

&lt;p&gt;After fixing headers, repeat-view performance improved dramatically.&lt;/p&gt;


&lt;h2&gt;
  
  
  3. Redis: Cache Expensive Shared Computations
&lt;/h2&gt;

&lt;p&gt;Redis wasn’t about caching everything.&lt;/p&gt;

&lt;p&gt;It was about preventing repeated fan-out queries:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Region summaries&lt;/li&gt;
&lt;li&gt;Uptime aggregates&lt;/li&gt;
&lt;li&gt;Incident rollups
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="s"&gt;"status:public:v1:region_summary"&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ok&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;redis&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="n"&gt;ok&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;computeRegionSummaryFromDB&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;// TTL + jitter to prevent stampedes&lt;/span&gt;
&lt;span class="n"&gt;ttl&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;30&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Second&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rand&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Intn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Second&lt;/span&gt;
&lt;span class="n"&gt;redis&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ttl&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Redis acted as a shock absorber between traffic spikes and the database.&lt;/p&gt;

&lt;p&gt;Short TTLs. Shared expensive work cached. Fresh enough, stable enough.&lt;/p&gt;


&lt;h2&gt;
  
  
  4. In-Process Cache: Stop Hitting Redis for Ultra-Hot Keys
&lt;/h2&gt;

&lt;p&gt;Once Redis is in place, the next bottleneck can be Redis itself.&lt;/p&gt;

&lt;p&gt;For ultra-hot keys, a tiny in-memory cache helps.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ok&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;memCache&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="n"&gt;ok&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;redisOrDB&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;memCache&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Second&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It’s a small change, but shaving a few milliseconds off thousands of requests per minute adds up.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. Filesystem Cache: Serve Pre-Rendered Output
&lt;/h2&gt;

&lt;p&gt;For the hottest pages, I cached rendered artifacts on disk.&lt;/p&gt;

&lt;p&gt;Conceptually:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Render final HTML&lt;/li&gt;
&lt;li&gt;Write to disk with version/timestamp key&lt;/li&gt;
&lt;li&gt;Serve directly when fresh&lt;/li&gt;
&lt;li&gt;Regenerate in background when stale&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sometimes “read file and return it” beats “query + render + serialize.”&lt;/p&gt;




&lt;h2&gt;
  
  
  6. HTTP Revalidation: Cheap Refreshes (304 &amp;gt; 200)
&lt;/h2&gt;

&lt;p&gt;Even when HTML can’t be cached long-term, refreshes can still be cheap.&lt;/p&gt;

&lt;p&gt;Short-lived HTML + ETag / Last-Modified means many refreshes become:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;304 Not Modified&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That’s huge during incidents when users refresh constantly.&lt;/p&gt;




&lt;h2&gt;
  
  
  7. Asset Minification + Smaller Hydration Surface
&lt;/h2&gt;

&lt;p&gt;I treated asset size like a performance budget.&lt;br&gt;
The JavaScript bundle alone went from ~1MB to ~45KB after removing unnecessary hydration and minifying aggressively.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Minified JS/CSS (Terser)&lt;/li&gt;
&lt;li&gt;Removed unused CSS&lt;/li&gt;
&lt;li&gt;Compressed with zstd/gzip&lt;/li&gt;
&lt;li&gt;Cached fingerprinted assets as immutable&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And most importantly:&lt;/p&gt;

&lt;p&gt;I reduced client-side hydration.&lt;/p&gt;

&lt;p&gt;Status pages are content-first.&lt;br&gt;
They don’t need SPA-level JavaScript.&lt;/p&gt;

&lt;p&gt;If the page works without JavaScript, it’s already fast.&lt;br&gt;
Then you add JS only where needed.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Layered Caching Model
&lt;/h2&gt;

&lt;p&gt;What I ended up with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Browser cache for immutable assets&lt;/li&gt;
&lt;li&gt;Short-lived HTML + revalidation&lt;/li&gt;
&lt;li&gt;Redis for shared expensive reads&lt;/li&gt;
&lt;li&gt;In-process cache for ultra-hot keys&lt;/li&gt;
&lt;li&gt;Optional filesystem cache for rendered artifacts&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each layer reduces work for the layer beneath it.&lt;/p&gt;

&lt;p&gt;That’s why the gains stack instead of overlapping.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Takeaway
&lt;/h2&gt;

&lt;p&gt;For many systems, third-party CDNs absolutely make sense.&lt;/p&gt;

&lt;p&gt;For incident communication paths, control often beats theoretical edge distribution.&lt;/p&gt;

&lt;p&gt;Removing third-party runtime dependencies did not hurt performance.&lt;/p&gt;

&lt;p&gt;It removed hidden latency.&lt;br&gt;
It reduced the failure surface.&lt;br&gt;
It improved repeat-visit behavior.&lt;/p&gt;

&lt;p&gt;For status pages, predictability beats theoretical edge performance.&lt;/p&gt;

&lt;p&gt;If a status page exists for when things break, it should be built like things will break.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>devops</category>
      <category>performance</category>
      <category>saas</category>
    </item>
    <item>
      <title>Why a Status Page Should Not Depend on Third-Party CDNs</title>
      <dc:creator>Nikola</dc:creator>
      <pubDate>Sun, 08 Feb 2026 12:52:07 +0000</pubDate>
      <link>https://dev.to/dragstor/why-a-status-page-should-not-depend-on-third-party-cdns-gk</link>
      <guid>https://dev.to/dragstor/why-a-status-page-should-not-depend-on-third-party-cdns-gk</guid>
      <description>&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; I ended up self-hosting all assets. Nothing broke. Performance improved. &lt;del&gt;Follow-up coming.&lt;/del&gt; Follow-up:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.to/dragstor/removing-third-party-dependencies-made-my-status-page-faster-heres-how-4a17"&gt;https://dev.to/dragstor/removing-third-party-dependencies-made-my-status-page-faster-heres-how-4a17&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;A status page exists for exactly one reason:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;to be reachable when everything else is broken.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;And yet, a surprising number of status pages depend on the same third-party infrastructure that often causes the outage in the first place.&lt;/p&gt;

&lt;p&gt;This isn’t a theoretical problem. It’s an architectural contradiction.&lt;/p&gt;




&lt;h2&gt;
  
  
  TL;DR (for busy engineers and founders)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Status pages are &lt;strong&gt;critical infrastructure&lt;/strong&gt;, not marketing assets
&lt;/li&gt;
&lt;li&gt;Third-party CDNs (including major ones) &lt;em&gt;do&lt;/em&gt; have global outages
&lt;/li&gt;
&lt;li&gt;When a CDN fails, status pages that depend on it often fail silently
&lt;/li&gt;
&lt;li&gt;A &lt;code&gt;200 OK&lt;/code&gt; page that doesn’t render correctly destroys trust
&lt;/li&gt;
&lt;li&gt;Fewer dependencies &amp;gt; better incident communication
&lt;/li&gt;
&lt;li&gt;Boring, self-hosted, dependency-light status pages outperform pretty ones during real outages
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If your status page can go down during an incident, it’s not doing its job.&lt;/p&gt;




&lt;p&gt;Let’s talk about why relying on third-party CDNs for status pages is a bad idea, what breaks in practice, and which tradeoffs are usually swept under the rug.&lt;/p&gt;




&lt;h2&gt;
  
  
  Real Recent Outages (2025–2026)
&lt;/h2&gt;

&lt;p&gt;CDNs and edge providers occasionally fail, often in dramatic fashion:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Cloudflare global outage - November 18, 2025&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
A faulty configuration change caused widespread HTTP 5xx errors across Cloudflare’s network, impacting services such as ChatGPT, X (Twitter), Spotify, and others.&lt;br&gt;&lt;br&gt;
&lt;a href="https://www.forbes.com/sites/kateoflahertyuk/2025/12/05/cloudflare-down-new-outage-takes-internet-down-again/" rel="noopener noreferrer"&gt;https://www.forbes.com/sites/kateoflahertyuk/2025/12/05/cloudflare-down-new-outage-takes-internet-down-again/&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Cloudflare outage - December 5, 2025&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Less than three weeks later, another Cloudflare incident affected roughly 28% of all HTTP traffic served by its network due to internal system failures.&lt;br&gt;&lt;br&gt;
&lt;a href="https://blog.cloudflare.com/5-december-2025-outage/" rel="noopener noreferrer"&gt;https://blog.cloudflare.com/5-december-2025-outage/&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Secondary impact on monitoring and reporting tools&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
During these outages, even third-party outage trackers struggled because they relied on the same CDN infrastructure.&lt;br&gt;&lt;br&gt;
&lt;a href="https://deployflow.co/blog/cloudflare-outage-explained/" rel="noopener noreferrer"&gt;https://deployflow.co/blog/cloudflare-outage-explained/&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;These weren’t cyberattacks. They were internal misconfigurations and cascading failures that propagated globally because of shared infrastructure.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;AWS CloudFront outage - February 10, 2026&lt;/strong&gt;
Amazon CloudFront suffered a global incident affecting DNS resolution and propagation of configuration changes. Some distributions returned NXDOMAIN, and any changes to CloudFront configs or even creation of new distributions were delayed for hours. Cache invalidations still worked, but that didn’t help teams trying to ship fixes during the outage.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://thenightly.com.au/society/technology/aws-outage-update-amazon-web-services-cloudfront-experience-global-outage-operation-issue-c-21597705" rel="noopener noreferrer"&gt;https://thenightly.com.au/society/technology/aws-outage-update-amazon-web-services-cloudfront-experience-global-outage-operation-issue-c-21597705&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In short: if your app or status page depended on CloudFront, you might have been up, but unable to change or recover anything when it mattered most.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Core Paradox
&lt;/h2&gt;

&lt;p&gt;When users visit your status page, something has already gone wrong.&lt;/p&gt;

&lt;p&gt;Their app doesn’t load.&lt;br&gt;&lt;br&gt;
Their API calls fail.&lt;br&gt;&lt;br&gt;
Their team chat is on fire.&lt;/p&gt;

&lt;p&gt;Now add this to the mix:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your main app is down
&lt;/li&gt;
&lt;li&gt;Your CDN is degraded or unreachable
&lt;/li&gt;
&lt;li&gt;Your status page is… also unreachable
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You’ve created a &lt;strong&gt;single point of communication failure&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;At that moment, the status page isn’t merely useless.&lt;br&gt;&lt;br&gt;
It actively increases frustration, support tickets, and distrust.&lt;/p&gt;




&lt;h2&gt;
  
  
  “But CDNs Are Highly Available”
&lt;/h2&gt;

&lt;p&gt;Usually.&lt;/p&gt;

&lt;p&gt;Until they aren’t.&lt;/p&gt;

&lt;p&gt;CDNs can fail in inconvenient ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;DNS resolution issues
&lt;/li&gt;
&lt;li&gt;Regional routing failures
&lt;/li&gt;
&lt;li&gt;TLS or certificate problems
&lt;/li&gt;
&lt;li&gt;Cached error pages that refuse to expire
&lt;/li&gt;
&lt;li&gt;Partial outages that affect “only some users”
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And when CDNs fail, they often fail &lt;strong&gt;globally&lt;/strong&gt;, loudly, and at exactly the wrong time.&lt;/p&gt;

&lt;p&gt;A status page should not share blast radius with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your main application&lt;/li&gt;
&lt;li&gt;Your analytics stack&lt;/li&gt;
&lt;li&gt;Your marketing site&lt;/li&gt;
&lt;li&gt;Someone else’s JavaScript experiment&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The Silent Failure Mode Nobody Talks About
&lt;/h2&gt;

&lt;p&gt;Here’s the one that causes the most damage.&lt;/p&gt;

&lt;p&gt;Your status page responds with &lt;code&gt;200 OK&lt;/code&gt;, but:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;External CSS doesn’t load
&lt;/li&gt;
&lt;li&gt;Fonts time out
&lt;/li&gt;
&lt;li&gt;JavaScript never arrives
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What users see:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Unstyled text
&lt;/li&gt;
&lt;li&gt;Blank screens
&lt;/li&gt;
&lt;li&gt;Infinite loading indicators
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What support teams hear:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;“It works for me.”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What users think:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;“They’re hiding something.”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Trust dies quietly here.&lt;/p&gt;




&lt;h2&gt;
  
  
  Incident Communication Is a Critical Path
&lt;/h2&gt;

&lt;p&gt;During an incident, your status page becomes &lt;strong&gt;critical infrastructure&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It is not:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A marketing surface
&lt;/li&gt;
&lt;li&gt;A design showcase
&lt;/li&gt;
&lt;li&gt;A frontend playground
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Its job is brutally simple:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Load fast
&lt;/li&gt;
&lt;li&gt;Load reliably
&lt;/li&gt;
&lt;li&gt;Say something truthful
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Every external dependency increases the chance that it fails at the exact moment you need it most.&lt;/p&gt;




&lt;h2&gt;
  
  
  “Self-Hosting Everything Is Overkill”
&lt;/h2&gt;

&lt;p&gt;It isn’t. It’s an intentional constraint.&lt;/p&gt;

&lt;p&gt;Self-hosting forces discipline:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Smaller payloads
&lt;/li&gt;
&lt;li&gt;Fewer scripts
&lt;/li&gt;
&lt;li&gt;Fewer fonts
&lt;/li&gt;
&lt;li&gt;Fewer clever ideas
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A status page does not need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Five font weights
&lt;/li&gt;
&lt;li&gt;Client-side hydration
&lt;/li&gt;
&lt;li&gt;A/B testing
&lt;/li&gt;
&lt;li&gt;Analytics beacons firing during outages
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It needs to render. Period.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Tradeoffs (Because Yes, They Exist)
&lt;/h2&gt;

&lt;p&gt;Avoiding third-party CDNs means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You handle asset delivery yourself
&lt;/li&gt;
&lt;li&gt;You lose some edge caching convenience
&lt;/li&gt;
&lt;li&gt;You think about cache headers and invalidation
&lt;/li&gt;
&lt;li&gt;You accept “good enough” over perfect Lighthouse scores
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ask the real question:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Do you want your status page optimized for benchmarks, or for reality?&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  A Simple Rule of Thumb
&lt;/h2&gt;

&lt;p&gt;If a dependency can fail as part of the same incident you’re communicating about, it should not be required for your status page to load.&lt;/p&gt;

&lt;p&gt;That includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CDNs serving your status page assets&lt;/li&gt;
&lt;li&gt;External analytics&lt;/li&gt;
&lt;li&gt;Third-party fonts&lt;/li&gt;
&lt;li&gt;Tag managers&lt;/li&gt;
&lt;li&gt;Anything that blocks rendering while phoning home&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Your product may depend on shared infrastructure.&lt;br&gt;
Your status page should not.&lt;/p&gt;

&lt;p&gt;Assume the outage affects more than just your app. Design accordingly.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Uncomfortable Truth
&lt;/h2&gt;

&lt;p&gt;Most status pages are designed for calm days, not bad days.&lt;/p&gt;

&lt;p&gt;They look great in screenshots.&lt;br&gt;&lt;br&gt;
They demo well.&lt;br&gt;&lt;br&gt;
They fail quietly when they matter most.&lt;/p&gt;

&lt;p&gt;A status page should be boring, resilient, and slightly paranoid.&lt;/p&gt;

&lt;p&gt;That’s not a flaw.&lt;/p&gt;

&lt;p&gt;That’s the point.&lt;/p&gt;

&lt;p&gt;I’m building &lt;a href="https://StatusPage.me?ref=dev.to"&gt;StatusPage.me&lt;/a&gt; around this exact constraint: incident comms that don’t collapse when edge networks do.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>devops</category>
      <category>saas</category>
      <category>sre</category>
    </item>
  </channel>
</rss>
