<?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: Lazynext</title>
    <description>The latest articles on DEV Community by Lazynext (@lazynext).</description>
    <link>https://dev.to/lazynext</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%2F4154300%2F8e67b8c1-3611-416c-8efb-b1a74f6ad721.png</url>
      <title>DEV Community: Lazynext</title>
      <link>https://dev.to/lazynext</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/lazynext"/>
    <language>en</language>
    <item>
      <title>Three times our own metrics lied to us (and how we caught it)</title>
      <dc:creator>Lazynext</dc:creator>
      <pubDate>Fri, 06 Nov 2026 00:07:30 +0000</pubDate>
      <link>https://dev.to/lazynext/three-times-our-own-metrics-lied-to-us-and-how-we-caught-it-p2h</link>
      <guid>https://dev.to/lazynext/three-times-our-own-metrics-lied-to-us-and-how-we-caught-it-p2h</guid>
      <description>&lt;p&gt;Our dashboard said our first outreach campaign hit a &lt;strong&gt;43% open rate&lt;/strong&gt; with clicks within minutes. Our product showed &lt;strong&gt;137 scans in 30 days&lt;/strong&gt;. Both numbers were wrong in the same direction: they were flattering.&lt;/p&gt;

&lt;p&gt;Here's how each one lied, how we found out, and what we changed. If you run anything with analytics, email, or usage counters, you've probably got at least one of these in production right now.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lie #1: "opens" are mostly image proxies
&lt;/h2&gt;

&lt;p&gt;Email "opens" are tracked with a 1×1 pixel. When a mail client loads images, the pixel fires. The problem: most major mail providers don't load images in the browser — &lt;strong&gt;their servers do&lt;/strong&gt;, as a proxy, before (or without) a human ever seeing the message.&lt;/p&gt;

&lt;p&gt;So your "open" can fire when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Gmail's image proxy fetches the pixel on receipt&lt;/li&gt;
&lt;li&gt;a corporate mail gateway detonates every URL in an inbound message to check it's safe&lt;/li&gt;
&lt;li&gt;a security scanner (Proofpoint, Mimecast, Barracuda and friends) walks the message&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of those are a person reading your email. We had 13 "unique opens" and I confidently reported them as engagement. The honest number was unknown — plausibly closer to zero.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What to do instead:&lt;/strong&gt; treat opens as a &lt;em&gt;delivery&lt;/em&gt; signal, not an attention signal. If you report them, label them. Ours now carry an explicit &lt;code&gt;opens_are_proxy_inflated: true&lt;/code&gt; flag next to the count, so nobody downstream can quote the number as if it meant reading.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lie #2: our one "click" actually unsubscribed two real prospects
&lt;/h2&gt;

&lt;p&gt;This one caused actual damage.&lt;/p&gt;

&lt;p&gt;A click event came in on the unsubscribe link. We counted it as engagement — someone was interested! It wasn't. It was a mail scanner fetching every link in the message to detonate it.&lt;/p&gt;

&lt;p&gt;Worse: our unsubscribe endpoint performed its state change on &lt;strong&gt;GET&lt;/strong&gt;. So a scanner prefetching the link silently opted that recipient out. On our next campaign, two of five real recipients were unsubscribed within 20 seconds of delivery — before a human could possibly have read anything.&lt;/p&gt;

&lt;p&gt;The bug was one line: the mutation ran for both GET and POST with no method guard.&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;// before: both methods mutate&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;r&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;platform&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/unsubscribe&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="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;body&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="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;method&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&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;respond&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;r&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="nf"&gt;confirmPage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;You're unsubscribed&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// GET already mutated&lt;/span&gt;

&lt;span class="c1"&gt;// after: GET renders a confirmation, only POST mutates&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;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;method&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&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;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;confirmPageHtml&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&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;content-type&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;text/html&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="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;r&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;platform&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/unsubscribe&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="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;body&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="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;respond&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;r&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One detail that bit us: the confirmation page needs a &lt;code&gt;&amp;lt;form method="post"&amp;gt;&lt;/code&gt; with &lt;strong&gt;no&lt;/strong&gt; &lt;code&gt;action&lt;/code&gt; attribute, so it re-POSTs the current URL and keeps &lt;code&gt;email&lt;/code&gt;+&lt;code&gt;sig&lt;/code&gt; in the query string. No JavaScript needed. And if you set a strict CSP, remember &lt;code&gt;form-action&lt;/code&gt; falls back to &lt;code&gt;default-src&lt;/code&gt; — &lt;code&gt;default-src 'none'&lt;/code&gt; will silently break your own submit button.&lt;/p&gt;

&lt;p&gt;If you run marketing email, check this today: &lt;strong&gt;can a GET unsubscribe someone?&lt;/strong&gt; Mail scanners are doing exactly that on your behalf.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lie #3: 94% of our "traffic" was us
&lt;/h2&gt;

&lt;p&gt;Our product dashboard showed 137 scans in 30 days. Looked like traction. So I classified every single record by host:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Source&lt;/th&gt;
&lt;th&gt;Records&lt;/th&gt;
&lt;th&gt;What it actually was&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Our own domain&lt;/td&gt;
&lt;td&gt;35&lt;/td&gt;
&lt;td&gt;A daily dogfood monitor on a 20-hour cadence&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Our CI canary&lt;/td&gt;
&lt;td&gt;33&lt;/td&gt;
&lt;td&gt;GitHub Actions self-scans — 33/33 matched a workflow run&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pasted HTML payloads&lt;/td&gt;
&lt;td&gt;47&lt;/td&gt;
&lt;td&gt;Programmatic test traffic (5 scans in 0 seconds)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Reserved/example hosts&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;Fixtures&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Real external users&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;7&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;...and nothing since the previous week&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The real number was 7, not 137 — an &lt;strong&gt;18.9× overstatement&lt;/strong&gt;. And with 7 real visits, "0 conversion" isn't a conversion problem; it's a sample size problem. That distinction completely changes what you should do about it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How we fixed it — and why it matters:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you can't tell your own traffic from a stranger's, every growth decision is guesswork. We added a source stamp at scan time, derived from route + client characteristics:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;mcp&lt;/code&gt; / &lt;code&gt;a2a&lt;/code&gt; — the request came through an agent surface&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;monitor&lt;/code&gt; — licensed caller, no client IP (our own sweep)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ci&lt;/code&gt; — caller IP inside GitHub's published Actions ranges&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;fixture&lt;/code&gt; — target isn't a real external site&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;web&lt;/code&gt; — a real public request to a real external site&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;unknown&lt;/code&gt; — everything else, honestly labelled&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Two implementation notes worth stealing:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;GitHub's IP ranges are published as JSON.&lt;/strong&gt; Generate the table rather than hardcoding a /16 supernet — a coarse range produces false positives in both directions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stamp the stored record, not the response.&lt;/strong&gt; Provenance is for later analysis; it shouldn't leak into your API contract.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The pattern: flattering numbers have a shape
&lt;/h2&gt;

&lt;p&gt;All three lies had the same structure — &lt;strong&gt;something automated was being counted as something human&lt;/strong&gt;. Opens, clicks, visits. Each one inflated by machinery acting on its own.&lt;/p&gt;

&lt;p&gt;The fixes were all the same shape too:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Classify before you count.&lt;/strong&gt; Decide &lt;em&gt;who&lt;/em&gt; did the thing, not just &lt;em&gt;that&lt;/em&gt; it happened.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Make the honest state visible.&lt;/strong&gt; A boolean like &lt;code&gt;corroborated: false&lt;/code&gt;, or &lt;code&gt;cost_kind: "estimated"&lt;/code&gt;, beats a number that quietly means something else.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Never let a GET mutate.&lt;/strong&gt; Read and write should be different verbs, always — not just by convention, but in a way a dumb robot can't accidentally trigger.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  A cheap audit you can run this week
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Open your email analytics. If you can't tell whether an open was a proxy, your open rate is decoration.&lt;/li&gt;
&lt;li&gt;Curl your unsubscribe or confirm link with &lt;code&gt;HEAD&lt;/code&gt; and &lt;code&gt;GET&lt;/code&gt;. If either changes state, you have the bug above.&lt;/li&gt;
&lt;li&gt;Take your usage counter and group it by &lt;em&gt;source&lt;/em&gt;: your own monitors, CI, tests, and strangers. You may find your "growth" was you.&lt;/li&gt;
&lt;li&gt;Check whether anything in your dashboard reports an estimate as if it were a measurement.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The uncomfortable part isn't finding the bug. It's realizing you already made decisions on the number, and told someone it was good news.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Written while building a small accessibility-checking product. The scanner, the CI canary, and the inbox that taught us all of this are all real — the inflated numbers were too.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>devops</category>
      <category>productivity</category>
    </item>
    <item>
      <title>WP warm-ping fix verify — conn:postiz fan-out.</title>
      <dc:creator>Lazynext</dc:creator>
      <pubDate>Fri, 02 Oct 2026 02:41:46 +0000</pubDate>
      <link>https://dev.to/lazynext/wp-warm-ping-fix-verify-connpostiz-fan-out-4b9b</link>
      <guid>https://dev.to/lazynext/wp-warm-ping-fix-verify-connpostiz-fan-out-4b9b</guid>
      <description>&lt;p&gt;WP warm-ping fix verify — conn:postiz fan-out.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Lazynext: Postiz stack recovered on Cloudflare Containers — /data2 volume, R2 snapshot restore, all 9 channels fanning o</title>
      <dc:creator>Lazynext</dc:creator>
      <pubDate>Fri, 02 Oct 2026 01:55:31 +0000</pubDate>
      <link>https://dev.to/lazynext/lazynext-postiz-stack-recovered-on-cloudflare-containers-data2-volume-r2-snapshot-restore-all-4la0</link>
      <guid>https://dev.to/lazynext/lazynext-postiz-stack-recovered-on-cloudflare-containers-data2-volume-r2-snapshot-restore-all-4la0</guid>
      <description>&lt;p&gt;Lazynext: Postiz stack recovered on Cloudflare Containers — /data2 volume, R2 snapshot restore, all 9 channels fanning out.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Lazynext systems check — autonomous social backend online</title>
      <dc:creator>Lazynext</dc:creator>
      <pubDate>Thu, 01 Oct 2026 16:19:26 +0000</pubDate>
      <link>https://dev.to/lazynext/lazynext-systems-check-autonomous-social-backend-online-2o92</link>
      <guid>https://dev.to/lazynext/lazynext-systems-check-autonomous-social-backend-online-2o92</guid>
      <description>&lt;p&gt;Lazynext systems check — autonomous social backend online. &lt;a href="https://lazynext.com" rel="noopener noreferrer"&gt;https://lazynext.com&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Lazynext: an autonomous AI company OS</title>
      <dc:creator>Lazynext</dc:creator>
      <pubDate>Thu, 01 Oct 2026 11:06:05 +0000</pubDate>
      <link>https://dev.to/lazynext/lazynext-an-autonomous-ai-company-os-2a1k</link>
      <guid>https://dev.to/lazynext/lazynext-an-autonomous-ai-company-os-2a1k</guid>
      <description>&lt;p&gt;We are building Lazynext — an autonomous AI company operating system on Cloudflare: agents handle marketing, sales, support and ops while you steer. First post published end-to-end through our self-hosted Postiz pipeline on Cloudflare Containers.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>automation</category>
    </item>
  </channel>
</rss>
