<?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: Naga Pinupa</title>
    <description>The latest articles on DEV Community by Naga Pinupa (@nagapinupa).</description>
    <link>https://dev.to/nagapinupa</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%2F4242309%2Fd6f8ea73-52b7-4131-9cb7-7e9170ff8f83.png</url>
      <title>DEV Community: Naga Pinupa</title>
      <link>https://dev.to/nagapinupa</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/nagapinupa"/>
    <language>en</language>
    <item>
      <title>Never Retry a 400: The 10-Minute MuleSoft Fix That Stopped Our Production Noise</title>
      <dc:creator>Naga Pinupa</dc:creator>
      <pubDate>Fri, 13 Nov 2026 06:44:33 +0000</pubDate>
      <link>https://dev.to/nagapinupa/never-retry-a-400-the-10-minute-mulesoft-fix-that-stopped-our-production-noise-gop</link>
      <guid>https://dev.to/nagapinupa/never-retry-a-400-the-10-minute-mulesoft-fix-that-stopped-our-production-noise-gop</guid>
      <description>&lt;p&gt;We shipped a MuleSoft API that retried every failure — 400, 401, 403, all 3 times each. Same bad request, same error, 3x log noise, and the downstream system throttled us.&lt;/p&gt;

&lt;p&gt;It took us a while to notice, because nothing looked broken at first. The API was responding. The flows were completing. But our logs were full of the same failed request, repeated three times, and the downstream team started asking why we were hammering their system with requests that could never succeed.&lt;/p&gt;

&lt;p&gt;A 400 is not a flaky network. It is a bad request. Sending it again does not fix the payload, the missing field, or the invalid value — it just creates more noise, more alerts, and more load on a system that already told us no.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrong vs Right
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Wrong:&lt;/strong&gt; retry everything, three times, no questions asked.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Right:&lt;/strong&gt; retry only transient errors, with backoff — and fail fast on client errors.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- Retry ONLY transient errors --&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;&amp;lt;!-- 408, 500, 502, 503 -- with backoff: 2s, 4s, 8s --&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;&amp;lt;!-- Never retry: 400, 401, 403 --&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;until-successful&lt;/span&gt; &lt;span class="na"&gt;maxRetries&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"3"&lt;/span&gt;
    &lt;span class="na"&gt;millisBetweenRetries&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"2000"&lt;/span&gt;
    &lt;span class="na"&gt;doc:name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Retry transient errors only"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;http:request&lt;/span&gt; &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"GET"&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/orders"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/until-successful&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!-- In your error handler, decide before you retry: --&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;&amp;lt;!-- shouldRetry = [408, 500, 502, 503] contains httpStatus --&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;&amp;lt;!-- 400 -&amp;gt; bad request, fix the request --&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;&amp;lt;!-- 401 -&amp;gt; unauthorized, fix the credentials --&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;&amp;lt;!-- 403 -&amp;gt; forbidden, fix the permissions --&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;&amp;lt;!-- 408, 500, 502, 503 -&amp;gt; wait 2s, then 4s, then 8s, then give up --&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In practice, that meant moving the retry decision out of a blanket policy and into a simple status check: if the status is transient, retry with increasing backoff. If it is a client error, stop immediately, log it once, and surface it clearly.&lt;/p&gt;

&lt;p&gt;The fix took about ten minutes. The production noise dropped immediately.&lt;/p&gt;

&lt;h2&gt;
  
  
  3 Rules
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Retry only transient errors.&lt;/strong&gt; 408, 500, 502, and 503 can be temporary. A retry might actually help.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Never retry a 400 — the request is wrong.&lt;/strong&gt; The same request will fail the same way every time. Retrying it is just repeating the mistake.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Backoff, don't hammer.&lt;/strong&gt; Wait 2s, then 4s, then 8s. Give the downstream system time to recover instead of adding to the overload.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Closing
&lt;/h2&gt;

&lt;p&gt;Most MuleSoft APIs don't fail in DataWeave, they fail in production on the retry policy nobody reviewed.&lt;/p&gt;

&lt;p&gt;What retry mistake have you seen in prod?&lt;/p&gt;

</description>
      <category>mulesoft</category>
      <category>api</category>
      <category>integration</category>
      <category>dataweave</category>
    </item>
  </channel>
</rss>
