<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Resilience | The .NET Blog</title><link>https://thedotnetblog.com/tags/resilience/</link><description>Articles, tutorials and insights from the .NET community.</description><generator>Hugo</generator><language>en</language><managingEditor>@thedotnetblog (The .NET Blog)</managingEditor><webMaster>@thedotnetblog</webMaster><lastBuildDate>Thu, 21 May 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://thedotnetblog.com/tags/resilience/index.xml" rel="self" type="application/rss+xml"/><item><title>Stop Hammering a Struggling Dependency: Retry Patterns for Azure Functions + Service Bus</title><link>https://thedotnetblog.com/news/emiliano-montesdeoca/azure-functions-service-bus-exponential-backoff-circuit-breaker/</link><pubDate>Thu, 21 May 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/news/emiliano-montesdeoca/azure-functions-service-bus-exponential-backoff-circuit-breaker/</guid><description>Exponential backoff and circuit breaker patterns are now natively supported for Service Bus-triggered Azure Functions — here's how they work and why you want both.</description><content:encoded>&lt;p&gt;Here&amp;rsquo;s how a recoverable fault becomes an outage in a Functions app: a dependency starts timing out, every Function instance retries immediately and indefinitely, the dependency gets hammered with hundreds of concurrent failed requests, and what started as a transient hiccup turns into a system-wide backpressure event.&lt;/p&gt;
&lt;p&gt;You probably know this story. Azure Functions scale out fast — that&amp;rsquo;s the whole point. But &amp;ldquo;scale out fast&amp;rdquo; and &amp;ldquo;retry immediately&amp;rdquo; together can make failures dramatically worse.&lt;/p&gt;
&lt;p&gt;Two patterns help. Exponential backoff and circuit breaker. Both are now natively supported for Service Bus-triggered Azure Functions.&lt;/p&gt;
&lt;h2 id="two-patterns-different-roles"&gt;Two Patterns, Different Roles&lt;/h2&gt;
&lt;p&gt;These patterns are complementary, not alternatives:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Exponential backoff&lt;/strong&gt; answers: &lt;em&gt;when should I try again?&lt;/em&gt;
It increases the delay between retries so a dependency has time to recover. Message-level, pacing the retry timing.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Circuit breaker&lt;/strong&gt; answers: &lt;em&gt;should I call this dependency at all right now?&lt;/em&gt;
It stops repeated calls to an unhealthy dependency after a failure threshold is hit, then probes carefully after a cooldown period. System-level, preventing retry storms.&lt;/p&gt;
&lt;p&gt;You want both. Backoff handles per-message retry pacing. Circuit breaker handles aggregate health decisions.&lt;/p&gt;
&lt;h2 id="why-this-matters-especially-for-service-bus"&gt;Why This Matters Especially for Service Bus&lt;/h2&gt;
&lt;p&gt;The queue absorbs burst traffic, which is good. But without controls, the queue can grow while workers keep wasting compute on calls that will fail. Poison messages stay active longer than they should. Hot partitions or limited downstream capacity create cascading problems.&lt;/p&gt;
&lt;p&gt;The safer design:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Detect transient failure&lt;/li&gt;
&lt;li&gt;Delay the next attempt with exponential backoff&lt;/li&gt;
&lt;li&gt;Stop calling the dependency when a failure threshold is reached (circuit open)&lt;/li&gt;
&lt;li&gt;Resume carefully after a cooldown period (circuit probe)&lt;/li&gt;
&lt;li&gt;Move irrecoverable work to dead-letter or a quarantine path&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="what-the-native-support-looks-like"&gt;What the Native Support Looks Like&lt;/h2&gt;
&lt;p&gt;The new support integrates with the existing Azure Functions host model — no extra libraries, no custom implementations. Configuration goes in your &lt;code&gt;host.json&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;extensions&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;serviceBus&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;messageHandlerOptions&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;maxRetryCount&amp;#34;&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;retryPolicy&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;mode&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;exponentialBackoff&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;minBackoff&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;00:00:02&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;maxBackoff&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;00:05:00&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;maxRetryCount&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Circuit breaker configuration sets the failure threshold and reset interval so unhealthy dependencies don&amp;rsquo;t get pummeled during recovery.&lt;/p&gt;
&lt;h2 id="languages-covered"&gt;Languages Covered&lt;/h2&gt;
&lt;p&gt;This isn&amp;rsquo;t .NET only. The feature covers dotnet, JavaScript, TypeScript, and Python — the full set of Service Bus trigger supported languages in Azure Functions.&lt;/p&gt;
&lt;h2 id="wrapping-up"&gt;Wrapping Up&lt;/h2&gt;
&lt;p&gt;Retry patterns aren&amp;rsquo;t exciting to configure until the first time a downstream outage causes your Functions to compound the problem instead of gracefully degrading. Setting these up proactively is cheap. Retrofitting them during an incident is not.&lt;/p&gt;
&lt;p&gt;Original post: &lt;a href="https://devblogs.microsoft.com/azure-sdk/exponential-backoff-circuit-breaker-azure-functions/"&gt;Exponential backoff and circuit breaker for Service Bus-triggered Azure Functions&lt;/a&gt;&lt;/p&gt;</content:encoded></item></channel></rss>