<?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: Aubaid farroukh</title>
    <description>The latest articles on DEV Community by Aubaid farroukh (@aubaid_farroukh_882b5ec05).</description>
    <link>https://dev.to/aubaid_farroukh_882b5ec05</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%2F1515721%2F8bd4c239-d6cd-48a5-8e54-103144fe2237.png</url>
      <title>DEV Community: Aubaid farroukh</title>
      <link>https://dev.to/aubaid_farroukh_882b5ec05</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/aubaid_farroukh_882b5ec05"/>
    <language>en</language>
    <item>
      <title>I Built a Retry Library Because I Kept Losing Failed API Calls</title>
      <dc:creator>Aubaid farroukh</dc:creator>
      <pubDate>Mon, 31 Aug 2026 08:16:12 +0000</pubDate>
      <link>https://dev.to/aubaid_farroukh_882b5ec05/i-built-a-retry-library-because-i-kept-losing-failed-api-calls-3gn3</link>
      <guid>https://dev.to/aubaid_farroukh_882b5ec05/i-built-a-retry-library-because-i-kept-losing-failed-api-calls-3gn3</guid>
      <description>&lt;p&gt;Every retry library I found did the same thing: wrap a function, retry it a few times, throw if it still fails. &lt;br&gt;
Fine until the retries run out and the error just... disappears into a catch block. No record of what request failed, what it was trying to send, or why. I'd find out a webhook silently dropped three days later when someone asked why an order never synced.&lt;/p&gt;

&lt;p&gt;So I built smart-retry a small TypeScript retry library that does two things most others don't:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Drop-in Axios and Fetch clients, not just a generic wrapper function&lt;/li&gt;
&lt;li&gt;Automatic failure logging when a request exhausts all retries, it gets written to disk with its URL, method, headers, body, and error, so you can inspect or replay it later instead of losing it the moment it throws&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Quick look&lt;/strong&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;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createAxiosRetry&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@aubaid/smart-retry&lt;/span&gt;&lt;span class="dl"&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;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createAxiosRetry&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;maxRetries&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;backoff&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;exponential&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;p&gt;&lt;code&gt;const response = await client.get('https://api.example.com/users');&lt;/code&gt;&lt;br&gt;
If that fails after 5 attempts, you don't just get a thrown error — you get a log:&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;manager&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getRetryManager&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;failed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;manager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getFailedRequests&lt;/span&gt;&lt;span class="p"&gt;();&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;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;failed&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; requests logged`&lt;/span&gt;&lt;span class="p"&gt;);&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Log file:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;manager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getLogFilePath&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It only retries things worth retrying by default network errors, timeouts, 429s, and 5xx and you can override that with a shouldRetry callback.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Where I need help&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/AubaidFarrukh/smart-retry/issues/17" rel="noopener noreferrer"&gt;defaultShouldRetry doesn't retry Axios timeout errors&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/AubaidFarrukh/smart-retry/issues/18" rel="noopener noreferrer"&gt;AxiosRetry has zero test coverage&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/AubaidFarrukh/smart-retry/issues/19" rel="noopener noreferrer"&gt;No maxDelay cap for exponential backoff&lt;/a&gt; (already has a PR in progress!)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/AubaidFarrukh/smart-retry/issues/20" rel="noopener noreferrer"&gt;Reduce any usage in the public types&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/AubaidFarrukh/smart-retry/issues/21" rel="noopener noreferrer"&gt;README doesn't document log rotation config&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All labeled good first issue. &lt;a href="https://github.com/AubaidFarrukh/smart-retry/blob/main/CONTRIBUTING.md" rel="noopener noreferrer"&gt;CONTRIBUTING.md&lt;/a&gt; has the dev setup if you want to jump in.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm install @aubaid/smart-retry&lt;/code&gt;&lt;br&gt;
Repo: &lt;a href="https://github.com/AubaidFarrukh/smart-retry" rel="noopener noreferrer"&gt;https://github.com/AubaidFarrukh/smart-retry&lt;/a&gt; issues, PRs, and "this API is weird" feedback all welcome.&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>javascript</category>
      <category>opensource</category>
      <category>node</category>
    </item>
  </channel>
</rss>
