<?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: GetLogFlow</title>
    <description>The latest articles on DEV Community by GetLogFlow (logflow).</description>
    <link>https://dev.to/logflow</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%2F14055%2F7d139dc5-fe6d-4951-b1e5-98d51efbcf44.png</url>
      <title>DEV Community: GetLogFlow</title>
      <link>https://dev.to/logflow</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/logflow"/>
    <language>en</language>
    <item>
      <title>The Silent Bug That Cost $28,000: Why Empty Catch Blocks Are the Most Expensive Code You'll Ever Write</title>
      <dc:creator>Alexandr Bandurchin</dc:creator>
      <pubDate>Fri, 17 Jul 2026 15:09:25 +0000</pubDate>
      <link>https://dev.to/logflow/the-silent-bug-that-cost-28000-why-empty-catch-blocks-are-the-most-expensive-code-youll-ever-460a</link>
      <guid>https://dev.to/logflow/the-silent-bug-that-cost-28000-why-empty-catch-blocks-are-the-most-expensive-code-youll-ever-460a</guid>
      <description>&lt;p&gt;A checkout flow silently fails for 12% of users. No errors in Sentry. No alerts firing. HTTP 200 everywhere. Users click "Pay" and nothing happens. For two weeks.&lt;/p&gt;

&lt;p&gt;This isn't a hypothetical — it's a pattern that plays out at startups every month. Here's the anatomy of how it happens and the logging setup that prevents it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The anatomy of a silent failure
&lt;/h2&gt;

&lt;p&gt;A payment service calls Stripe, gets a response, and publishes an event to a message queue. The consumer picks it up and updates the order status. Straightforward architecture.&lt;/p&gt;

&lt;p&gt;Then Stripe adds a new field to their response object. The serializer chokes on a &lt;code&gt;BigInt&lt;/code&gt; value. An exception is thrown. The catch block swallows it. The function returns &lt;code&gt;undefined&lt;/code&gt;.&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="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// TODO: handle this&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The order stays in "pending" forever. The user sees a spinner. No error is logged. No alert fires. The HTTP response is still 200 because the endpoint technically "succeeded."&lt;/p&gt;

&lt;p&gt;340 failed checkouts. $28,000 in lost revenue. Discovered by accident.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why traditional monitoring misses this
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Sentry&lt;/strong&gt; — nothing to report. The error was caught and swallowed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;APM dashboards&lt;/strong&gt; — all green. Response times normal, HTTP status codes normal.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Uptime monitoring&lt;/strong&gt; — the service is up. It's responding. It's just not doing what it's supposed to do.&lt;/p&gt;

&lt;p&gt;This is the gap between "the service is running" and "the service is working correctly." Traditional monitoring watches the first. Almost nobody watches the second.&lt;/p&gt;

&lt;h2&gt;
  
  
  The fix: log business outcomes, not just errors
&lt;/h2&gt;

&lt;p&gt;The core problem isn't technical — it's philosophical. Most teams log infrastructure events (request received, database query executed, response sent) but not business outcomes (order created, payment processed, event published).&lt;/p&gt;

&lt;h3&gt;
  
  
  Before: logging the transport
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`POST /checkout completed in &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;ms&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;ms`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This tells you the endpoint responded. It doesn't tell you whether the payment actually went through.&lt;/p&gt;

&lt;h3&gt;
  
  
  After: logging the outcome
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Payment event published&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="nx"&gt;orderId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;stripePaymentId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;eventType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;payment.completed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="c1"&gt;// or&lt;/span&gt;
&lt;span class="nx"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&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;Payment event failed&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="nx"&gt;orderId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;stage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;serialization&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now there's a searchable record of what actually happened. Filter &lt;code&gt;level:error AND service:payment-service&lt;/code&gt; and the 340 failures show up immediately — with the exact error, the affected orders, and the timestamp when it started.&lt;/p&gt;

&lt;h2&gt;
  
  
  The five rules that prevent $28K bugs
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Every catch block logs the error
&lt;/h3&gt;

&lt;p&gt;No exceptions. No &lt;code&gt;// TODO&lt;/code&gt;. If something is caught, it's logged with full context:&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="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&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;Event serialization failed&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="nx"&gt;orderId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;stack&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stack&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;sanitize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;payload&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="nx"&gt;err&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Logs are structured JSON, not strings
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Useless at scale&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Payment failed for user &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// Queryable, filterable, alertable&lt;/span&gt;
&lt;span class="nx"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&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;Payment failed&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="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;orderId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;stripe&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;errorCode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;serialization_error&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Template strings can't be filtered. JSON fields can.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Every log includes business context
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;userId&lt;/code&gt;, &lt;code&gt;orderId&lt;/code&gt;, &lt;code&gt;amount&lt;/code&gt; — not just "something failed." When the alert fires at 2am, the difference between "500 errors in the last hour" and "500 payment failures affecting 340 unique users totaling $28,000" determines how fast the team responds.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Alert on error rate, not individual errors
&lt;/h3&gt;

&lt;p&gt;Individual error alerts are noisy. Error &lt;em&gt;rate&lt;/em&gt; alerts catch gradual degradation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Normal: 0.3% error rate (card declines)&lt;/li&gt;
&lt;li&gt;After the bug: 12% error rate&lt;/li&gt;
&lt;li&gt;Alert threshold: 2%&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A rate-based alert would have caught this on day one, not day fourteen.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Don't trust HTTP status codes
&lt;/h3&gt;

&lt;p&gt;The endpoint returned 200. The business logic failed. These are not contradictory statements — they're just measured at different layers.&lt;/p&gt;

&lt;p&gt;Log the business layer. Alert on the business layer. HTTP status codes are necessary but not sufficient.&lt;/p&gt;

&lt;h2&gt;
  
  
  The tooling question
&lt;/h2&gt;

&lt;p&gt;Structured logging needs somewhere to go. The options, roughly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;grep&lt;/code&gt; on the server&lt;/strong&gt; — works until there are multiple servers. Or until someone needs to search at 2am without SSH access.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ELK self-hosted&lt;/strong&gt; — powerful, but maintaining Elasticsearch becomes a second job.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enterprise platforms (Datadog, New Relic)&lt;/strong&gt; — built for teams with APM, infrastructure monitoring, and six-figure budgets. Overkill if the need is just log search + alerts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lightweight SaaS&lt;/strong&gt; — tools like LogFlow, Logtail, or Axiom that focus on log management without the full observability suite. Typically $19-49/month instead of $300+.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The tool matters less than the practice. Pick something that supports structured search and error rate alerts, and the specific vendor is a secondary decision.&lt;/p&gt;

&lt;h2&gt;
  
  
  The checklist
&lt;/h2&gt;

&lt;p&gt;Before the next deploy, audit these:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Every catch block logs the error with context&lt;/li&gt;
&lt;li&gt;[ ] Logs are structured JSON with queryable fields&lt;/li&gt;
&lt;li&gt;[ ] Business outcomes are logged (not just HTTP status)&lt;/li&gt;
&lt;li&gt;[ ] Logs go somewhere searchable (not just stdout)&lt;/li&gt;
&lt;li&gt;[ ] At least one error rate alert exists per critical service&lt;/li&gt;
&lt;li&gt;[ ] The alerting pipeline has been tested end-to-end&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The 30 minutes this takes will prevent the 6-hour debugging session. And the $28,000 invoice.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;📦 Try LogFlow free&lt;/strong&gt; — 1 GB/month, no credit card, 5-minute setup: &lt;a href="https://getlogflow.com" rel="noopener noreferrer"&gt;getlogflow.com&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;What's the most expensive silent bug you've encountered? The catch block? The missing log? The alert that wasn't configured?&lt;/em&gt;&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
