<?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: Web-Engineer</title>
    <description>The latest articles on DEV Community by Web-Engineer (web-engine).</description>
    <link>https://dev.to/web-engine</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%2Forganization%2Fprofile_image%2F15308%2Fbe5eedc7-e176-4578-aea9-b10a5e0c9db5.png</url>
      <title>DEV Community: Web-Engineer</title>
      <link>https://dev.to/web-engine</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/web-engine"/>
    <language>en</language>
    <item>
      <title>Failover beyond DNS</title>
      <dc:creator>Craig Lawson</dc:creator>
      <pubDate>Thu, 15 Oct 2026 15:11:32 +0000</pubDate>
      <link>https://dev.to/web-engine/failover-beyond-dns-1e36</link>
      <guid>https://dev.to/web-engine/failover-beyond-dns-1e36</guid>
      <description>&lt;p&gt;So you've built a service and it's running in the cloud. It sits in a Kubernetes cluster, it's designed for high availability, and every component has a replica. Then the data centre loses its connection to the internet, and none of that helps.&lt;/p&gt;

&lt;p&gt;It happens more often than we'd like to admit. Data centres with multiple independent points of presence still have outages. On 20 October 2025, a DNS fault inside AWS's US-EAST-1 region cascaded into hours of disruption for a long list of services that had nothing to do with each other, apart from where they were hosted. Cloudflare has had more than one bad day too, including an outage of its 1.1.1.1 DNS resolver in July 2025 and a network-wide failure that November. When a large share of the web sits on a handful of providers, one provider's bad afternoon becomes everyone's.&lt;/p&gt;

&lt;p&gt;The uncomfortable lesson is that your hardware can be perfectly healthy and you can still be offline. Spread yourself across data centres with failover between them, and a DNS problem can still undo the whole arrangement.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this mattered to us
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.web-engineer.co.uk/work/we-sentry" rel="noopener noreferrer"&gt;Web-Engine Sentry&lt;/a&gt; (Sentry for short) is our site-protection plugin. It cuts spam by making a site hard work for bots while keeping it easy for humans. It's built for &lt;a href="https://wordpress.org/plugins/web-engine-sentry/" rel="noopener noreferrer"&gt;WordPress&lt;/a&gt; first, and it ships with an &lt;a href="https://www.web-engineer.co.uk/doc/sentry-api" rel="noopener noreferrer"&gt;API&lt;/a&gt; and examples so it can protect any site. Sentry gives sites several ways to check that a visitor is real: captcha, email verification and mobile verification. As soon as a site puts one of those checks in front of its contact form or login page, our uptime becomes their uptime. If we're unreachable, their visitors can't get in touch or sign in.&lt;/p&gt;

&lt;p&gt;So "it's in the cloud" wasn't a good enough answer. We needed a plan that keeps the service running wherever possible, whatever fails underneath it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Option one: throw hardware at it
&lt;/h2&gt;

&lt;p&gt;You can solve most availability problems with hardware, if you have the budget. Large cloud providers do exactly that, and they price it in. For most teams, though, a purely hardware-based answer is expensive, and you're still bound by the physical limits of someone else's estate.&lt;/p&gt;

&lt;p&gt;The conventional approach would be to host in two geographic regions and use DNS failover to switch between them. It works, but it isn't instant. Once the primary goes down, health checks have to notice, records have to change, and resolvers around the world have to let go of cached answers. Short TTLs help, but not every resolver honours them. That leaves a window, often a few minutes, where requests fail. For a verification step sitting in front of someone's checkout, a few minutes is a long time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Option two: make the software smarter
&lt;/h2&gt;

&lt;p&gt;The alternative is to let the client decide. Give the consumer of the service an ordered list of endpoints, add some basic error handling, and when a request fails, move to the next one straight away.&lt;/p&gt;

&lt;p&gt;The real advantage is that those endpoints can be completely independent: different hosting, different networks, even different DNS providers. Failover no longer waits for a record to propagate. It happens on the next request, in milliseconds. Our weak point becomes our own code and the service itself, rather than the rigid physical constraints of our suppliers, and our own code is something we can test, improve and ship.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DNS failover vs client-side fallback&lt;/strong&gt;&lt;br&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%2Faac7q1a9nn9f6si2r75c.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%2Faac7q1a9nn9f6si2r75c.png" width="800" height="294"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The idea in its simplest form:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Simplified illustration, not the Sentry SDK itself&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ENDPOINTS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://a.example-primary.net&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://b.example-secondary.org&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://c.example-tertiary.io&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;callService&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;base&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;ENDPOINTS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;base&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AbortSignal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&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="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// network error or timeout: try the next endpoint&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;All endpoints unavailable&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Decentralise by design
&lt;/h2&gt;

&lt;p&gt;Real resilience comes from breaking the application into its key parts and giving each one its own availability strategy. Once you treat each component as a separate service, you can tune how each one fails over. Here's how that played out for Sentry.&lt;/p&gt;

&lt;h3&gt;
  
  
  DNS
&lt;/h3&gt;

&lt;p&gt;We spread our endpoints across several domains, each managed by a different DNS provider, with multiple endpoints behind each domain. If one provider has a bad day, the others are unaffected. Relatively short TTLs mean we can repoint routes quickly when we need to.&lt;/p&gt;

&lt;h3&gt;
  
  
  Frontend
&lt;/h3&gt;

&lt;p&gt;The browser script loads from whichever CDN endpoint is available. The frontend knows about the alternatives, so if a script fails to load it moves on to the next one. That gives us geographically separate fallbacks managed entirely on the visitor's side. Once it finds an endpoint that works, it sticks with it for the rest of the session, so visitors don't pay the cost of a failed attempt twice.&lt;/p&gt;

&lt;h3&gt;
  
  
  Backend
&lt;/h3&gt;

&lt;p&gt;On the site's own server, the Sentry SDK acts as a gateway to the available service endpoints. That pushed us to treat each backend as a separate node from the start and to design a proper synchronisation strategy between them. We had to decide early what the service provides and how to deliver it in a decentralised way, rather than bolting resilience on later.&lt;/p&gt;

&lt;h3&gt;
  
  
  Data
&lt;/h3&gt;

&lt;p&gt;Each node also runs its own separate database, holding a specific set of tables duplicated across several sites. Our APIs keep these in sync with the master. Some of that data is read-only reference data; the rest lets a node keep tracking activity on its own. That's enough for the service to keep running even when the primary site is unavailable. When the master comes back, each node syncs what it recorded back to it.&lt;/p&gt;

&lt;p&gt;Behind everything sits a highly available database cluster, and the nodes treat it as the ultimate source of truth. On paper, that cluster should never go down. We deliberately don't assume it won't. Making no promises about its availability gives us another layer of fault tolerance, and forced us to plan up front how data is reconciled once everything is back online.&lt;/p&gt;

&lt;h2&gt;
  
  
  The result
&lt;/h2&gt;

&lt;p&gt;None of this is exotic. It's a fallback list, some careful error handling, and the discipline to assume every layer can fail. Together those give a site running Sentry verification that keeps working through regional outages, DNS failures and the occasional very bad day in a data centre.&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%2F4aukbr6dh7f0m91p8f1q.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%2F4aukbr6dh7f0m91p8f1q.png" width="800" height="334"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it, and tell us what you think
&lt;/h2&gt;

&lt;p&gt;You can install Sentry from the &lt;a href="https://wordpress.org/plugins/web-engine-sentry/" rel="noopener noreferrer"&gt;WordPress plugin directory&lt;/a&gt;, or read more about &lt;a href="https://www.web-engineer.co.uk/work/we-sentry" rel="noopener noreferrer"&gt;Web-Engine Sentry&lt;/a&gt; and the &lt;a href="https://www.web-engineer.co.uk/doc/sentry-api" rel="noopener noreferrer"&gt;Sentry API&lt;/a&gt; to use it on any site.&lt;/p&gt;

&lt;p&gt;How do you handle failover in your own services? Have you been caught out by DNS? Join the discussion and let us know.&lt;/p&gt;

</description>
      <category>sentry</category>
      <category>highavailability</category>
      <category>failover</category>
      <category>dns</category>
    </item>
  </channel>
</rss>
