<?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: Mira John</title>
    <description>The latest articles on DEV Community by Mira John (@dnsnotify).</description>
    <link>https://dev.to/dnsnotify</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%2F4132997%2Facd65a8b-6bad-4291-ab09-74886334bd8f.png</url>
      <title>DEV Community: Mira John</title>
      <link>https://dev.to/dnsnotify</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/dnsnotify"/>
    <language>en</language>
    <item>
      <title>Catch DNS and Certificate Failures Before Your Client Hears the Complaints</title>
      <dc:creator>Mira John</dc:creator>
      <pubDate>Mon, 05 Oct 2026 08:00:00 +0000</pubDate>
      <link>https://dev.to/dnsnotify/catch-dns-and-certificate-failures-before-your-client-hears-the-complaints-5hc5</link>
      <guid>https://dev.to/dnsnotify/catch-dns-and-certificate-failures-before-your-client-hears-the-complaints-5hc5</guid>
      <description>&lt;p&gt;The client's website is managed by a separate web agency. It is excluded from your contract. You do not have the hosting login, the WordPress password or the certificate-renewal job.&lt;/p&gt;

&lt;p&gt;Then one of the client's customers opens the site and sees &lt;strong&gt;Your connection is not private&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;They send the screenshot to your client. Your client calls you.&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%2Fsog7en3qooe76scg6nje.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%2Fsog7en3qooe76scg6nje.png" alt="The client-customer escalation chain that preventative monitoring should reverse" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The web server may be running normally. Exchange may be healthy. The failure can sit entirely in public DNS, the certificate served at the edge, or an expired domain registration.&lt;/p&gt;

&lt;p&gt;None of that helps once a customer has shown your client the warning. The client is embarrassed, the fix becomes urgent and the relationship is suddenly under review.&lt;/p&gt;

&lt;p&gt;You may not own the system, but you can still monitor what the public sees. Responsibility and visibility are separate.&lt;/p&gt;

&lt;h2&gt;
  
  
  Staying out does not mean staying blind
&lt;/h2&gt;

&lt;p&gt;Do not accept operational responsibility for a website you do not host or maintain. Taking ownership of another supplier's WordPress security, plugin updates or deployment process creates risk you cannot control.&lt;/p&gt;

&lt;p&gt;Do monitor the small set of public signals that affect the client's business:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;does the public DNS still return the expected records?&lt;/li&gt;
&lt;li&gt;are the authoritative nameservers consistent?&lt;/li&gt;
&lt;li&gt;is the website serving the expected certificate?&lt;/li&gt;
&lt;li&gt;is that certificate approaching expiry?&lt;/li&gt;
&lt;li&gt;is the domain registration approaching expiry?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These checks require no access to the website, DNS provider or registrar. They change nothing. They tell you what the client's customers can see from outside.&lt;/p&gt;

&lt;p&gt;When something changes, tell the client and direct the incident to the supplier that owns the repair. You provide the warning without inheriting somebody else's platform.&lt;/p&gt;

&lt;h2&gt;
  
  
  Clients do not think in supplier boundaries
&lt;/h2&gt;

&lt;p&gt;An MSP sees a website supplier, a hosting supplier, a registrar and perhaps a separate marketing agency.&lt;/p&gt;

&lt;p&gt;The client sees one company website and one company email address.&lt;/p&gt;

&lt;p&gt;Their customers see even less. They see an unsafe warning, a dead page or a bounced sales email. They do not care whether the certificate belongs to the web agency or the MX record belongs to the IT provider.&lt;/p&gt;

&lt;p&gt;That is why the order of discovery matters so much:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The client's customer sees the failure.&lt;/li&gt;
&lt;li&gt;The customer tells the client.&lt;/li&gt;
&lt;li&gt;The client becomes embarrassed and alarmed.&lt;/li&gt;
&lt;li&gt;The client calls whichever supplier they trust to explain it.&lt;/li&gt;
&lt;li&gt;Planned work stops and the incident becomes urgent.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Reverse that order and the same technical fault becomes much easier:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A quiet outside-in monitor notices a change.&lt;/li&gt;
&lt;li&gt;You check whether the result is real.&lt;/li&gt;
&lt;li&gt;You identify the responsible supplier.&lt;/li&gt;
&lt;li&gt;You contact the client with an explanation and a next step.&lt;/li&gt;
&lt;li&gt;The client's customers may never see the failure.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The email version is worse
&lt;/h2&gt;

&lt;p&gt;A certificate warning is visible immediately. Broken email can stay hidden.&lt;/p&gt;

&lt;p&gt;A potential customer sends a message to the client's sales address. It comes back as unreachable. The sender knows first. Your client hears next. You hear last.&lt;/p&gt;

&lt;p&gt;By then nobody can say how many enquiries failed or how long the problem existed.&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%2Fk50cuuu2zyzlhpk9kb6r.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%2Fk50cuuu2zyzlhpk9kb6r.png" alt="A customer email bounces before the client or MSP knows there is a problem" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The website may still be online with a green uptime check while the MX route is missing, SPF is broken or a nameserver migration has dropped records. Watching the homepage alone does not cover the public infrastructure behind email.&lt;/p&gt;

&lt;h2&gt;
  
  
  Visibility is not another security service
&lt;/h2&gt;

&lt;p&gt;Do not turn this into another sprawling security product.&lt;/p&gt;

&lt;p&gt;You do not need AI analysis of vaguely similar domains, a speculative risk score or another dashboard full of unrelated modules. Those features create more alerts and more arguments about ownership.&lt;/p&gt;

&lt;p&gt;The useful service is smaller:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;watch the public state the client depends on;&lt;/li&gt;
&lt;li&gt;remain quiet while it is unchanged;&lt;/li&gt;
&lt;li&gt;report the old and new values when it changes;&lt;/li&gt;
&lt;li&gt;let the responsible human decide what the change means.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You get independent visibility without taking ownership of the repair.&lt;/p&gt;

&lt;h2&gt;
  
  
  A cheap warning for an expensive conversation
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://dnsnotify.com/" rel="noopener noreferrer"&gt;DNS Notify&lt;/a&gt; provides that outside-in layer for DNS changes, served certificates and domain expiry. It does not require DNS-provider credentials and does not modify the systems it watches.&lt;/p&gt;

&lt;p&gt;It costs £5 per month for five domains, or £50 per year. On the annual plan that is about 83p per domain per month.&lt;/p&gt;

&lt;p&gt;For an MSP or agency, the choice is direct: pay less than £1 per domain each month for an early warning, or let the client's customer report the failure and turn a routine fix into a client-retention problem.&lt;/p&gt;

&lt;p&gt;You do not have to own the website to be the first professional who notices.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>webdev</category>
      <category>monitoring</category>
      <category>security</category>
    </item>
    <item>
      <title>Catch an Expired Certificate Before Your Client Hears “Your Website Is Unsafe”</title>
      <dc:creator>Mira John</dc:creator>
      <pubDate>Wed, 30 Sep 2026 08:00:00 +0000</pubDate>
      <link>https://dev.to/dnsnotify/ssl-certificate-expiry-monitoring-when-certificates-only-last-47-days-o63</link>
      <guid>https://dev.to/dnsnotify/ssl-certificate-expiry-monitoring-when-certificates-only-last-47-days-o63</guid>
      <description>&lt;p&gt;A customer opens your client's website and Chrome shows the warning everyone recognises: &lt;strong&gt;Your connection is not private.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;They take a screenshot and send it to your client. Your client sends it to you. A certificate renewal that should have been routine is now public, embarrassing and urgent.&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%2Fsog7en3qooe76scg6nje.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%2Fsog7en3qooe76scg6nje.png" alt="The certificate warning a client's customer should never be the first to report" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once that screenshot reaches the client, a routine renewal failure becomes an urgent incident. Check the certificate customers actually receive from outside the network. You do not need access to the website or its renewal system, and you do not need to own the repair.&lt;/p&gt;

&lt;p&gt;Since 15 March 2026 no public certificate authority will issue you a TLS certificate valid for more than 200 days. In March 2027 the cap drops to 100 days, and in March 2029 to 47. The last of the old 398-day certificates run out in April 2027, and after that everybody is on the short schedule whether they planned for it or not.&lt;/p&gt;

&lt;p&gt;The CA/Browser Forum voted this through in April 2025 (ballot SC-081v3), with Apple, Google, Microsoft and Mozilla all in favour. The reasoning is sound. Revocation has never worked well in browsers, so the practical way to limit the damage from a stolen or mis-issued certificate is to make it expire sooner.&lt;/p&gt;

&lt;p&gt;The part I care about is what it does to failure. At eight renewals a year nobody renews by hand, so nobody forgets. What happens instead is that the automation stops working and nothing tells you.&lt;/p&gt;

&lt;h2&gt;
  
  
  Five ways automated renewal fails quietly
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;The job stopped running.&lt;/strong&gt; The server was rebuilt and the cron entry or systemd timer wasn't carried over. The container image was rebuilt without the ACME client. Nothing logs an error, because nothing runs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The certificate renewed and the server never reloaded.&lt;/strong&gt; The ACME client wrote new files and exited. nginx, HAProxy or Postfix are still serving the old certificate from memory and will keep doing so until somebody restarts them. The renewal log says success. There is a longer write-up of this one, with the other places an old certificate hides, in &lt;a href="https://dnsnotify.com/guides/renewed-certificate-old-one-still-served/" rel="noopener noreferrer"&gt;renewed the certificate, old one still served&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It renewed on the wrong machine.&lt;/strong&gt; You renewed on the origin. Visitors talk to a load balancer, a CDN, or the second box in the pool, and each of those has its own copy.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The challenge started failing.&lt;/strong&gt; A firewall rule now blocks port 80. The DNS API token used for DNS-01 was rotated. Someone added a CAA record that doesn't include your CA. A CAA mistake used to bite once a year. At 47 days it bites eight times a year.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The validation expired.&lt;/strong&gt; The same ballot shortens how long a CA may reuse a domain validation, down to 10 days by 2029. Setups that leaned on a long-lived validation will have to prove control again at nearly every renewal.&lt;/p&gt;

&lt;p&gt;What these have in common is that the certificate on disk, the renewal log, or both look fine. The only place the problem is visible is from outside, in the certificate visitors are actually handed.&lt;/p&gt;

&lt;h2&gt;
  
  
  The one check that catches all five
&lt;/h2&gt;

&lt;p&gt;Connect the way a browser does and read what comes back:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; | openssl s_client &lt;span class="nt"&gt;-connect&lt;/span&gt; www.example.com:443 &lt;span class="nt"&gt;-servername&lt;/span&gt; www.example.com 2&amp;gt;/dev/null &lt;span class="se"&gt;\&lt;/span&gt;
  | openssl x509 &lt;span class="nt"&gt;-noout&lt;/span&gt; &lt;span class="nt"&gt;-issuer&lt;/span&gt; &lt;span class="nt"&gt;-serial&lt;/span&gt; &lt;span class="nt"&gt;-enddate&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Keep the &lt;code&gt;-servername&lt;/code&gt;. Without SNI, a server that hosts several sites hands you its default certificate, which may not be the one you think you're checking.&lt;/p&gt;

&lt;p&gt;Run that on a schedule, from a machine that is not the one doing the renewing, for every hostname that answers on 443. &lt;code&gt;example.com&lt;/code&gt; and &lt;code&gt;www.example.com&lt;/code&gt; can serve different certificates. So can &lt;code&gt;api.&lt;/code&gt;, &lt;code&gt;mail.&lt;/code&gt; and whatever sits behind your CDN. If a disk fills up on the box that renews, you don't want the warning to live on the same disk.&lt;/p&gt;

&lt;p&gt;If you want to spot-check a hostname without a terminal, this &lt;a href="https://dnsnotify.com/ssl-certificate-checker/" rel="noopener noreferrer"&gt;SSL certificate checker&lt;/a&gt; makes the same connection and shows the expiry, days left, issuer, serial and fingerprint.&lt;/p&gt;

&lt;h2&gt;
  
  
  How early to warn
&lt;/h2&gt;

&lt;p&gt;The classic advice is a 30-day warning. On a 47-day certificate that renews at around day 30, a 30-day warning is true for most of the certificate's life. It fires constantly, so people filter it, and then it is worthless on the one day it matters.&lt;/p&gt;

&lt;p&gt;Work backwards from the renewal point instead. If your client renews with a third of the lifetime left, a healthy 47-day certificate never drops below about 15 days remaining. A first warning at 14 days then means "renewal should have happened by now and didn't". After that you want reminders that get harder to ignore, and a final one that means a person has to act today. I settled on 14, 7, 3 and 1.&lt;/p&gt;

&lt;p&gt;Two more rules kept the noise down for me, the same way they did for DNS records in &lt;a href="https://dev.to/dnsnotify/dns-change-monitoring-the-seven-false-alarms-i-had-to-kill-hh3"&gt;the seven false alarms post&lt;/a&gt;. A new serial with a later expiry is a renewal, so it goes on a timeline and nobody gets an email. A new serial with an &lt;em&gt;earlier&lt;/em&gt; expiry does get an email, because that usually means someone installed the wrong file.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where this fits
&lt;/h2&gt;

&lt;p&gt;Certificate expiry is one of four things I watch per domain in &lt;a href="https://dnsnotify.com/" rel="noopener noreferrer"&gt;DNS Notify&lt;/a&gt;, next to DNS records, nameservers and the registration. Its &lt;a href="https://dnsnotify.com/ssl-certificate-expiry-monitoring/" rel="noopener noreferrer"&gt;SSL certificate expiry monitoring&lt;/a&gt; is deliberately narrow. It reads the leaf certificate served on port 443 and tracks the dates, issuer, key and fingerprint. It does not grade your TLS configuration or validate the chain, because other tools already do that well.&lt;/p&gt;

&lt;p&gt;Certificates also fail for DNS reasons. A CAA record that blocks your CA and a broken &lt;code&gt;_acme-challenge&lt;/code&gt; CNAME are both DNS changes, which is part of why the two live in one product. I covered the email equivalent of this, records that break without anyone noticing, in &lt;a href="https://dev.to/dnsnotify/email-dns-monitoring-the-four-records-that-break-mail-while-your-site-stays-up-ckl"&gt;the four records that break mail while your site stays up&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you do one thing this quarter, list every hostname you serve over HTTPS and check that each one is renewed by a machine, reloaded by a hook, and read from outside by something that will tell you when the first two stop working.&lt;/p&gt;

</description>
      <category>security</category>
      <category>devops</category>
      <category>ssl</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Catch Broken Email DNS Before Your Client Hears “Your Messages Are Bouncing”</title>
      <dc:creator>Mira John</dc:creator>
      <pubDate>Fri, 25 Sep 2026 08:00:00 +0000</pubDate>
      <link>https://dev.to/dnsnotify/email-dns-monitoring-the-four-records-that-break-mail-while-your-site-stays-up-ckl</link>
      <guid>https://dev.to/dnsnotify/email-dns-monitoring-the-four-records-that-break-mail-while-your-site-stays-up-ckl</guid>
      <description>&lt;p&gt;A potential customer emails your client's sales address. Seconds later the message comes back: &lt;strong&gt;address not found&lt;/strong&gt;, &lt;strong&gt;mailbox unavailable&lt;/strong&gt;, or &lt;strong&gt;domain could not be reached&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;That customer sees the failure first. They tell your client. Your client calls you. By then nobody knows how many enquiries were lost, and a small DNS problem has become an embarrassing business problem.&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%2Fk50cuuu2zyzlhpk9kb6r.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%2Fk50cuuu2zyzlhpk9kb6r.png" alt="A customer email bouncing before the client or MSP knows there is a problem" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Exchange can be healthy. The mail server can be running. Every internal dashboard can be green. If the public MX, SPF, DKIM or DMARC records are missing or wrong, customers still see the failure.&lt;/p&gt;

&lt;p&gt;A homepage uptime check will never catch it. Web and email share a domain name and almost nothing else. The website depends on an A, AAAA or CNAME record. Email depends on four different DNS records that an ordinary website check never reads.&lt;/p&gt;

&lt;p&gt;Staying out of a client's mail platform does not mean staying blind. An MSP, agency or developer can watch these four public records from the outside and warn the client before the client's customers become the monitoring system.&lt;/p&gt;

&lt;p&gt;Here are the four, how each one usually gets broken, and how to check it from a terminal.&lt;/p&gt;

&lt;h2&gt;
  
  
  MX: where your mail is delivered
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dig example.com MX +short
10 mail1.example.net.
20 mail2.example.net.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;MX records tell every other mail server where to deliver mail for your domain. They break during migrations. Someone moves the domain to a new DNS provider and the zone import drops a record, or keeps an MX for a mailbox provider you left two years ago. They also break when a domain changes hands inside a company and the new owner rebuilds the zone from memory.&lt;/p&gt;

&lt;p&gt;A wrong MX does not bounce mail straight away. If the listed host is gone, senders keep retrying for days before they give up. If it still accepts mail for your domain, the mail is delivered, into a mailbox nobody reads.&lt;/p&gt;

&lt;p&gt;MX record monitoring is the easiest kind to justify, because the record almost never changes and when it does the meaning is obvious. If you want to see what a domain publishes right now, this &lt;a href="https://dnsnotify.com/mx-lookup/" rel="noopener noreferrer"&gt;MX lookup&lt;/a&gt; asks the domain's own nameservers instead of a cache.&lt;/p&gt;

&lt;h2&gt;
  
  
  SPF: who may send as you
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dig example.com TXT +short | &lt;span class="nb"&gt;grep &lt;/span&gt;spf1
&lt;span class="s2"&gt;"v=spf1 include:_spf.google.com include:sendgrid.net -all"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;SPF is a TXT record at the apex of the domain, which is its weakness. The apex collects TXT records from every service that ever asked you to verify ownership. A year later somebody cleans up the junk, and the SPF line looks like junk too.&lt;/p&gt;

&lt;p&gt;The other common break is a second SPF record. A new tool's setup guide says to add &lt;code&gt;v=spf1 include:newtool.com ~all&lt;/code&gt;, and someone adds it as a new record instead of merging it into the existing one. Two SPF records is a permanent error, and receivers treat it as no SPF at all.&lt;/p&gt;

&lt;p&gt;Either way your mail still sends. It just starts failing authentication at the other end, and you hear about it from a customer weeks later.&lt;/p&gt;

&lt;h2&gt;
  
  
  DKIM: the key that signs your mail
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dig selector1._domainkey.example.com TXT +short
dig selector1._domainkey.example.com CNAME +short
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;DKIM public keys live under selector names that mean nothing to a person reading the zone. &lt;code&gt;s1._domainkey&lt;/code&gt;, &lt;code&gt;k2._domainkey&lt;/code&gt;, &lt;code&gt;mte1._domainkey&lt;/code&gt;. They look like leftovers, and they get deleted as leftovers. Your provider keeps signing with the private key, receivers can no longer find the public one, and every signature fails.&lt;/p&gt;

&lt;p&gt;You need the selector name to query it, and most people don't remember theirs. Send yourself an email and look for &lt;code&gt;s=&lt;/code&gt; in the &lt;code&gt;DKIM-Signature&lt;/code&gt; header, or run a &lt;a href="https://dnsnotify.com/dns-scanner/" rel="noopener noreferrer"&gt;DNS record scanner&lt;/a&gt; that tries the common selector names against your domain.&lt;/p&gt;

&lt;h2&gt;
  
  
  DMARC: what receivers do when the checks fail
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dig _dmarc.example.com TXT +short
&lt;span class="s2"&gt;"v=DMARC1; p=reject; rua=mailto:dmarc@example.com"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;DMARC ties SPF and DKIM together and tells receivers what to do with mail that fails both. The usual accident here is a debugging session. Deliverability is bad, someone sets &lt;code&gt;p=none&lt;/code&gt; to rule DMARC out, the real cause turns out to be something else, and the policy never goes back to &lt;code&gt;reject&lt;/code&gt;. Nothing breaks. You have just quietly stopped telling the world to refuse forged mail from your domain, and no test you own will ever notice.&lt;/p&gt;

&lt;p&gt;The other one to watch is the &lt;code&gt;rua&lt;/code&gt; address. If it changes to an address you don't recognise, your aggregate reports, which list every IP sending as you, are going to someone else.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to do about it
&lt;/h2&gt;

&lt;p&gt;All four are plain DNS records, so the dig commands above are most of a monitor already. Run them on a schedule, compare with the values you expect, and send yourself the old and new value when they differ. I went through the ways that comparison produces false alarms in &lt;a href="https://dev.to/dnsnotify/dns-change-monitoring-the-seven-false-alarms-i-had-to-kill-hh3"&gt;an earlier post&lt;/a&gt;. For email records the two that matter are to query the authoritative nameservers, and to join split TXT strings before comparing. SPF and DKIM values are long enough to be split into several strings, and servers don't always split them the same way twice.&lt;/p&gt;

&lt;p&gt;This is also what I built &lt;a href="https://dnsnotify.com/" rel="noopener noreferrer"&gt;DNS Notify&lt;/a&gt; to do. Its &lt;a href="https://dnsnotify.com/email-dns-monitoring/" rel="noopener noreferrer"&gt;email DNS monitoring&lt;/a&gt; watches the MX set, the SPF and DMARC records and whichever DKIM selectors you pick, and the alert is the record name with the accepted value and the current value next to each other. It doesn't validate SPF syntax or read DMARC reports. There are good tools for both and it isn't trying to be them. It tells you a record changed, within minutes, while you can still remember who was in the DNS panel that day.&lt;/p&gt;

&lt;p&gt;Whichever way you do it, write down the four values today. The hardest part of fixing a broken SPF record is working out what it used to say.&lt;/p&gt;

</description>
      <category>dns</category>
      <category>email</category>
      <category>devops</category>
      <category>security</category>
    </item>
    <item>
      <title>Detect Website and Email Failures Before Someone Tells Your Client</title>
      <dc:creator>Mira John</dc:creator>
      <pubDate>Mon, 21 Sep 2026 06:30:00 +0000</pubDate>
      <link>https://dev.to/dnsnotify/the-worst-way-to-discover-an-outage-your-clients-customer-finds-it-first-3nap</link>
      <guid>https://dev.to/dnsnotify/the-worst-way-to-discover-an-outage-your-clients-customer-finds-it-first-3nap</guid>
      <description>&lt;p&gt;Imagine the message arriving in the middle of an ordinary working day:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;One of our customers just sent us this screenshot. Why does our website say it is unsafe?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The screenshot is the browser warning everybody recognises: &lt;strong&gt;Your connection is not private.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fsog7en3qooe76scg6nje.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%2Fsog7en3qooe76scg6nje.png" alt="A Chrome-style certificate warning shown to a client's customer" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The customer saw it first. They told your client. Your client is now forwarding it to you.&lt;/p&gt;

&lt;p&gt;By then the failure is public and you are reacting on the client's schedule.&lt;/p&gt;

&lt;p&gt;The same thing happens with email:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A customer says their message to our sales address bounced back as unreachable. How long has this been happening?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The sender sees the failure first: “address not found”, “mailbox unavailable” or “domain could not be reached.”&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%2Fk50cuuu2zyzlhpk9kb6r.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%2Fk50cuuu2zyzlhpk9kb6r.png" alt="A bounced customer email caused by an MX or DNS failure" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The web server can be up. Exchange can be healthy. Every internal dashboard can be green. A missing MX record, wrong nameserver, expired certificate or lapsed domain can still make those working systems unreachable from outside.&lt;/p&gt;

&lt;p&gt;Your client did not discover the problem from an internal alert. Their customer received the failure and had to find another way to make contact.&lt;/p&gt;

&lt;p&gt;Now the failure is public. Your client is embarrassed in front of their own customer, does not know how much business may have been missed, and immediately wonders what they are paying you to look after.&lt;/p&gt;

&lt;h2&gt;
  
  
  You no longer control the schedule
&lt;/h2&gt;

&lt;p&gt;Five minutes earlier, you had a plan for the day.&lt;/p&gt;

&lt;p&gt;Now you have to stop everything.&lt;/p&gt;

&lt;p&gt;The certificate warning, broken DNS record or missing MX route may be straightforward to fix. That does not make the situation small. Once the client knows, the work becomes urgent regardless of what else you were doing.&lt;/p&gt;

&lt;p&gt;You need to investigate immediately, send updates, coordinate with whichever supplier owns the affected system, and explain why nobody noticed first.&lt;/p&gt;

&lt;p&gt;For an employee, the same escalation may reach a boss before it reaches the technical team. For an agency or MSP, it can put the entire client relationship under review.&lt;/p&gt;

&lt;p&gt;The technical incident may last an hour. The doubt it creates can last much longer.&lt;/p&gt;

&lt;h2&gt;
  
  
  The failure may sit outside your contract
&lt;/h2&gt;

&lt;p&gt;This problem is not limited to infrastructure you directly manage.&lt;/p&gt;

&lt;p&gt;An MSP may not host the client's website. A web agency may not manage the client's mail service. A developer may have no access to the registrar. That does not make early visibility useless.&lt;/p&gt;

&lt;p&gt;If the MSP sees that the public website or served certificate has failed, it can warn the client and direct the incident to the web team. If the web agency sees that an MX record changed or disappeared, it can tell the client to contact IT before customers start reporting bounced messages.&lt;/p&gt;

&lt;p&gt;You do not need to own the repair to provide the early warning.&lt;/p&gt;

&lt;p&gt;That is valuable because clients rarely think in supplier boundaries while something is broken. They see one business, one website and one email address. Whoever notices early looks proactive. Whoever learns from the client's customer looks absent.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quiet monitoring beats another noisy dashboard
&lt;/h2&gt;

&lt;p&gt;More alerts are not the answer.&lt;/p&gt;

&lt;p&gt;An agency or MSP does not need AI to classify every vaguely similar registered domain as a critical risk. It does not need a growing bundle of unrelated security modules. That noise makes the real changes easier to miss.&lt;/p&gt;

&lt;p&gt;The useful contract is simpler:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;watch the public DNS records that matter;&lt;/li&gt;
&lt;li&gt;watch the certificate actually served by the website;&lt;/li&gt;
&lt;li&gt;watch the domain's expiry state;&lt;/li&gt;
&lt;li&gt;stay quiet while the state is unchanged;&lt;/li&gt;
&lt;li&gt;alert when something meaningful changes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is outside-in monitoring. It checks what customers can actually reach rather than trusting that a provider dashboard, renewal job or configuration file must be correct.&lt;/p&gt;

&lt;p&gt;A certificate may renew successfully on disk while the public endpoint continues to serve the old certificate. A DNS control panel may show the intended MX record while an authoritative server returns something else. A domain-renewal notice may be sitting in the inbox of somebody who left the company two years ago.&lt;/p&gt;

&lt;p&gt;The public result is what affects the client.&lt;/p&gt;

&lt;h2&gt;
  
  
  A day earlier is a different kind of incident
&lt;/h2&gt;

&lt;p&gt;Some warnings arrive days or weeks early: certificate expiry, domain expiry, and planned DNS changes that do not look right.&lt;/p&gt;

&lt;p&gt;Other changes need attention as soon as they are visible: an MX record disappearing, nameservers disagreeing, or a critical DNS value changing unexpectedly.&lt;/p&gt;

&lt;p&gt;Either way, an internal alert changes the nature of the work.&lt;/p&gt;

&lt;p&gt;Instead of dropping everything after an embarrassed phone call, you can investigate, identify the responsible supplier, prepare the fix, and contact the client with an answer already in hand.&lt;/p&gt;

&lt;p&gt;Sometimes the client never needs to see the failure at all.&lt;/p&gt;

&lt;p&gt;That is the difference between reactive support and preventative monitoring.&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%2Fgol3d7y1remfd34vcxa4.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%2Fgol3d7y1remfd34vcxa4.png" alt="The client discovers it first versus DNS Notify warning the supplier first" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  A deliberately small tool for a costly problem
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://dnsnotify.com/" rel="noopener noreferrer"&gt;DNS Notify&lt;/a&gt; monitors DNS changes, SSL certificates and domain expiry from outside the provider account. It does not need DNS-provider credentials, does not change DNS, and does not use AI to manufacture extra findings. It is designed to stay quiet until the monitored state changes.&lt;/p&gt;

&lt;p&gt;It costs £5 per month for five domains, or £50 per year. On the annual plan that is about &lt;strong&gt;83p per domain per month&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The choice is not really between monitoring and doing nothing.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;losing a client after their customers discover the problem;&lt;/li&gt;
&lt;li&gt;abandoning planned work and fixing it in a panic; or&lt;/li&gt;
&lt;li&gt;paying less than £1 per domain per month to hear about important changes as soon as possible.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Which would you choose?&lt;/p&gt;

&lt;p&gt;You can also use the &lt;a href="https://dnsnotify.com/dns-scanner/" rel="noopener noreferrer"&gt;free DNS, MX, certificate and domain-expiry tools&lt;/a&gt; without creating an account.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>webdev</category>
      <category>monitoring</category>
      <category>dns</category>
    </item>
    <item>
      <title>DNS change monitoring: the seven false alarms I had to kill</title>
      <dc:creator>Mira John</dc:creator>
      <pubDate>Sat, 19 Sep 2026 14:28:30 +0000</pubDate>
      <link>https://dev.to/dnsnotify/dns-change-monitoring-the-seven-false-alarms-i-had-to-kill-hh3</link>
      <guid>https://dev.to/dnsnotify/dns-change-monitoring-the-seven-false-alarms-i-had-to-kill-hh3</guid>
      <description>&lt;p&gt;A client's customer should never be the first person to tell you that the website is unsafe, email is bouncing, or a DNS change broke something public. By then the failure is already embarrassing, your client is asking what they are paying you for, and a routine fix has become an interruption.&lt;/p&gt;

&lt;p&gt;The catch is that a noisy monitor is almost as bad as no monitor. If it sends false alarms every time answer order changes or a resolver cache catches up, people stop reading it. The useful monitor stays quiet until a meaningful public state changes.&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%2Fgol3d7y1remfd34vcxa4.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%2Fgol3d7y1remfd34vcxa4.png" alt="A quiet alert changes who discovers the problem first" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The first version of any DNS checker is about ten lines. Look up a record, compare it with the value stored last time, send an email if they differ. Point that at a real domain for a day or two and it will email you about records nobody has touched. The checker behind &lt;a href="https://dnsnotify.com/" rel="noopener noreferrer"&gt;DNS Notify&lt;/a&gt; started there too.&lt;/p&gt;

&lt;p&gt;DNS change monitoring is easy to describe and annoying to get right, because DNS answers vary in ways that mean nothing. Below are the false alarms I had to design out, and what I did about each. If you want to monitor DNS changes with your own script, this should save you a week.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Asking a resolver instead of the source
&lt;/h2&gt;

&lt;p&gt;The obvious way to look up a record is through the system resolver, which is what &lt;code&gt;dig example.com MX&lt;/code&gt; does by default. A recursive resolver answers from cache until the TTL runs out. Public resolvers are also big anycast clusters, so two queries a minute apart can land on machines with different cache contents. After a real change you can see old, new, old, new until the TTL has run out everywhere. To a naive checker each flip is a change.&lt;/p&gt;

&lt;p&gt;The fix is to skip resolvers and ask the domain's own nameservers. With dig:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dig example.com NS +short
dig @ns1.example-dns.net example.com MX +noall +answer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And with dnspython, which is what the checker uses:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;dns.resolver&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;authoritative_answer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;domain&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rtype&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;ns_hosts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;dns&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;resolver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;domain&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;NS&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
    &lt;span class="n"&gt;ns_ips&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_text&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;ns_hosts&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;dns&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;resolver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;A&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;

    &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dns&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;resolver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Resolver&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;configure&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nameservers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ns_ips&lt;/span&gt;
    &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lifetime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;

    &lt;span class="n"&gt;ans&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rtype&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;raise_on_no_answer&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_text&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;rd&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;ans&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rrset&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;ans&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rrset&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you only want to eyeball one record this way, I put the same logic behind a free &lt;a href="https://dnsnotify.com/dns-lookup/" rel="noopener noreferrer"&gt;authoritative DNS lookup&lt;/a&gt; so you don't need a terminal.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Answer order
&lt;/h2&gt;

&lt;p&gt;Many nameservers rotate multi-value answers on purpose. Two A records come back as &lt;code&gt;.10, .20&lt;/code&gt; and then as &lt;code&gt;.20, .10&lt;/code&gt;. A string comparison calls that a change. Sort the values before comparing. That is what the &lt;code&gt;sorted()&lt;/code&gt; in the snippet above is for.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. TTLs
&lt;/h2&gt;

&lt;p&gt;Store the full answer line, TTL included, and you are in trouble twice. From a resolver the TTL counts down, so every check differs from the last. From an authoritative server the TTL is stable, but people lower it before a migration and raise it afterwards, and that is not something anyone wants an email about. I keep the TTL for display and leave it out of the comparison.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. The SOA serial
&lt;/h2&gt;

&lt;p&gt;The SOA record carries a serial number that goes up whenever anything in the zone is edited. Some providers bump it on their own schedule too. Include the SOA in naive DNS record monitoring and you get an alert for every edit to every record, including the ones you already alert on. I mask the serial before comparing. If the serial is the only difference, the new SOA is accepted quietly. Changes to the primary nameserver or the timers still come through, and those are the ones that tell you something.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Timeouts that look like deletions
&lt;/h2&gt;

&lt;p&gt;A query that times out returns nothing. A record that was deleted also returns nothing. Treat them the same and every network blip becomes "your MX record was removed", which is a horrible email to get at 3am when it is not true.&lt;/p&gt;

&lt;p&gt;These need to be separate code paths. NXDOMAIN and an empty answer are real answers from the server. A timeout or SERVFAIL is a failed check and says nothing about the record. I count failures per record and only alert after four failed runs in a row. When the record comes back, the recovery goes on the timeline without a second email.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Formatting noise
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;Mail.Example.NET.&lt;/code&gt; and &lt;code&gt;mail.example.net&lt;/code&gt; are the same host. A long TXT record is sent as several quoted 255-byte strings, and where the splits fall is up to the server. Pick one canonical form and stick to it. The checker strips trailing dots, rebuilds MX and SRV answers field by field, and joins TXT strings into one value before comparing. SPF and DKIM records are where this bites, because they are the long ones.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Changes that undo themselves
&lt;/h2&gt;

&lt;p&gt;Someone fat-fingers a record, notices, and fixes it two minutes later. The first alert is fair. A second alert saying it changed again, back to what you expected, is noise. I keep two values per record, the accepted one and the current one. When current goes back to accepted, the pending flag clears and a "reverted" event is logged with no email.&lt;/p&gt;

&lt;p&gt;The same two-value model handles planned changes. After a migration you accept the new value and it becomes the baseline. Without that step the monitor nags forever about a change you made on purpose. I wrote the whole loop up as a guide, &lt;a href="https://dnsnotify.com/guides/how-to-monitor-dns-changes/" rel="noopener noreferrer"&gt;how to monitor DNS changes&lt;/a&gt;, with the dig commands for each step.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I could not fix
&lt;/h2&gt;

&lt;p&gt;Some records are supposed to differ depending on who asks. Latency-based routing, geo DNS and most CDNs return different A records from different places, and sometimes from the same place. No amount of normalising makes that a stable signal. I leave those records off the watch list and monitor the CNAME that points at the CDN instead. That one should never move without someone knowing.&lt;/p&gt;

&lt;h2&gt;
  
  
  What was left
&lt;/h2&gt;

&lt;p&gt;After all of that, the checker got boring, which was the goal. DNS change alerts are only worth having if people still open them in month six. It emails when a value at the source differs from the value someone accepted, and shows both. It waits before reporting failures. It logs reverts and recoveries without emailing them.&lt;/p&gt;

&lt;p&gt;This is how &lt;a href="https://dnsnotify.com/dns-change-monitoring/" rel="noopener noreferrer"&gt;DNS change monitoring&lt;/a&gt; works in DNS Notify today. The full rules, including how certificates and registration data are compared, are on the &lt;a href="https://dnsnotify.com/methodology/" rel="noopener noreferrer"&gt;methodology page&lt;/a&gt;. If you have run into a false alarm I have not listed, tell me in the comments. I would like to break the checker before a customer does.&lt;/p&gt;

</description>
      <category>dns</category>
      <category>devops</category>
      <category>monitoring</category>
      <category>python</category>
    </item>
  </channel>
</rss>
