<?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: Klein Houzin</title>
    <description>The latest articles on DEV Community by Klein Houzin (@kleinhouzin).</description>
    <link>https://dev.to/kleinhouzin</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F342612%2Fb9558786-828c-4e1e-8533-df30a1300ced.jpg</url>
      <title>DEV Community: Klein Houzin</title>
      <link>https://dev.to/kleinhouzin</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kleinhouzin"/>
    <language>en</language>
    <item>
      <title>Implémenter une politique de logging pour les Equipes IT</title>
      <dc:creator>Klein Houzin</dc:creator>
      <pubDate>Thu, 23 Oct 2025 06:10:15 +0000</pubDate>
      <link>https://dev.to/kleinhouzin/implementer-une-politique-de-logging-pour-les-equipes-it-4khi</link>
      <guid>https://dev.to/kleinhouzin/implementer-une-politique-de-logging-pour-les-equipes-it-4khi</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Dans l'ère numérique actuelle, à l'époque de l'IA, les logs sont bien plus que de simples traces techniques - ce sont les yeux et les oreilles de votre infrastructure IT. Une politique de logging bien définie n'est pas un luxe, mais une nécessité stratégique pour toute entreprise soucieuse de sa sécurité et de sa performance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pourquoi une Politique de Logging Est Essentielle
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Les Enjeux Clés
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Sécurité : Détection des intrusions et menaces&lt;/li&gt;
&lt;li&gt;Conformité : Respect du RGPD et autres réglementations&lt;/li&gt;
&lt;li&gt;Performance : Monitoring des systèmes et applications&lt;/li&gt;
&lt;li&gt;Audit : Traçabilité complète des activités&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 Le saviez-vous ? Sans politique de logging, vous naviguez à l'aveugle en cas d'incident.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Les 5 Piliers d'une Politique de Logging Robuste
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Classification Intelligente des Logs
&lt;/h3&gt;

&lt;p&gt;Niveau  Usage   Conservation&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🔴 CRITIQUE Incidents majeurs   1 an&lt;/li&gt;
&lt;li&gt;🟠 ERREUR   Bugs fonctionnels   6 mois&lt;/li&gt;
&lt;li&gt;🟡 AVERTISSEMENT    Anomalies   3 mois&lt;/li&gt;
&lt;li&gt;🔵 INFORMATION  Activité normale   3 mois&lt;/li&gt;
&lt;li&gt;⚪ DEBUG Développement  30 jours&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Standardisation du Format
&lt;/h3&gt;

&lt;p&gt;Adoptez un format structuré comme le JSON pour faciliter l'analyse :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "timestamp": "2024-01-15T10:30:00Z",
  "level": "ERROR",
  "service": "app-métier",
  "user": "john.doe",
  "event": "authentification_failure",
  "message": "Échec connexion"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Sécurisation des Logs
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Chiffrement des données au repos&lt;/li&gt;
&lt;li&gt;Contrôle d'accès strict (principe du moindre privilège)&lt;/li&gt;
&lt;li&gt;Intégrité garantie contre les modifications&lt;/li&gt;
&lt;li&gt;Stockage sécurisé et dédié&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. Conservation Adaptée
&lt;/h3&gt;

&lt;p&gt;Ne gardez pas tout, mais gardez l'essentiel !&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Logs de sécurité : 1 an (conformité RGPD)&lt;/li&gt;
&lt;li&gt;Logs applicatifs : 6 mois (support technique)&lt;/li&gt;
&lt;li&gt;Logs de debug : 30 jours (développement)&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Tout ceci ne peut être fait qu'avec de bons outils. Mais de grâce, séparez vos logs debug et informations des logs d'erreurs. Ils n'ont pas la même durée de vie.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  5. Monitoring Actif
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Tableaux de bord temps réel&lt;/li&gt;
&lt;li&gt;Alertes automatiques sur comportements suspects&lt;/li&gt;
&lt;li&gt;Analytics prédictifs&lt;/li&gt;
&lt;li&gt;Rapports de conformité automatiques&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Mise en Œuvre : Par où Commencer ?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Phase 1 : Inventaire (Semaines 1-2)
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt; Cartographiez tous vos systèmes&lt;/li&gt;
&lt;li&gt; Identifiez les données critiques&lt;/li&gt;
&lt;li&gt; Priorisez les applications stratégiques&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Phase 2 : Standardisation (Semaines 3-4)
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt; Définissez vos formats de logs&lt;/li&gt;
&lt;li&gt; Configurez les niveaux de journalisation&lt;/li&gt;
&lt;li&gt; Implémentez les outils de collecte&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Phase 3 : Sécurisation (Semaines 5-6)
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt; Mettez en place le contrôle d'accès&lt;/li&gt;
&lt;li&gt; Chiffrez les données sensibles&lt;/li&gt;
&lt;li&gt; Automatisez les sauvegardes&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Bonnes Pratiques à Adopter Absolument
&lt;/h2&gt;

&lt;p&gt;À Faire&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Journalisez les tentatives d'authentification (succès et échecs)&lt;/li&gt;
&lt;li&gt;Tracez les accès aux données sensibles&lt;/li&gt;
&lt;li&gt;Monitoriez les modifications de configuration&lt;/li&gt;
&lt;li&gt;Conservez les logs de sécurité 1 an minimum&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;À Éviter&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ne journalisez pas les mots de passe en clair&lt;/li&gt;
&lt;li&gt;Ne surchargez pas avec des informations inutiles&lt;/li&gt;
&lt;li&gt;N'oubliez pas les aspects conformité légale&lt;/li&gt;
&lt;li&gt;Ne négligez pas la performance des applications&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Cas d'Usage : Sécurité et Conformité
&lt;/h2&gt;

&lt;p&gt;Détection d'Intrusion&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;02:15 - Tentative de connexion échouée (compte admin)&lt;/li&gt;
&lt;li&gt;02:16 - 50 tentatives depuis la même IP&lt;/li&gt;
&lt;li&gt;02:17 - Alerte automatique à l'équipe sécurité&lt;/li&gt;
&lt;li&gt;02:18 - Blocage de l'IP suspecte&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Audit RGPD&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Accès aux données personnelles tracés&lt;/li&gt;
&lt;li&gt;Consentements utilisateurs journalisés&lt;/li&gt;
&lt;li&gt;Droit à l'oubli implémenté&lt;/li&gt;
&lt;li&gt;Preuves de conformité disponibles&lt;/li&gt;
&lt;li&gt;Mesurer l'Efficacité de Votre Politique&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;** KPIs à Suivre **&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Temps de détection des incidents&lt;/li&gt;
&lt;li&gt;Nombre d'alertes pertinentes&lt;/li&gt;
&lt;li&gt;Couverture des systèmes journalisés&lt;/li&gt;
&lt;li&gt;Temps de rétention effectif&lt;/li&gt;
&lt;li&gt;Conformité aux réglementations&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Les Tendances Futures du Logging
&lt;/h2&gt;

&lt;p&gt;L'Avenir est ...&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Intelligent : IA pour l'analyse des logs (nous y reviendrons)&lt;/li&gt;
&lt;li&gt;Cloud Native : Solutions serverless&lt;/li&gt;
&lt;li&gt;Unifié : Centralisation multi-sources&lt;/li&gt;
&lt;li&gt;Temps Réel : Streaming et analytics instantanés (de grace n'allez pas au temps réel si personne n'est là pour monitorer)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion : Votre Plan d'Action
&lt;/h2&gt;

&lt;p&gt;Dès demain, vous pouvez :&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Auditer votre situation actuelle (très importante. Accepter la réalité ne crève pas les yeux)&lt;/li&gt;
&lt;li&gt;Définir les priorités de journalisation &lt;/li&gt;
&lt;li&gt;Former vos équipes aux bonnes pratiques (former surtout les équipes systèmes)&lt;/li&gt;
&lt;li&gt;Implémenter les outils de base &lt;/li&gt;
&lt;li&gt;Passer votre politique de logging dans votre prompt d'IA&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Dans 3 mois, vous pourrez :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ Détecter les incidents plus rapidement&lt;/li&gt;
&lt;li&gt;✅ Répondre aux audits en toute sérénité&lt;/li&gt;
&lt;li&gt;✅ Améliorer la performance de vos applications&lt;/li&gt;
&lt;li&gt;✅ Dormir sur vos deux oreilles !&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>logging</category>
      <category>solutionarchitect</category>
      <category>webdev</category>
    </item>
    <item>
      <title>🧠 Two “AllowedHosts” Every Developer Should Know</title>
      <dc:creator>Klein Houzin</dc:creator>
      <pubDate>Wed, 22 Oct 2025 04:04:31 +0000</pubDate>
      <link>https://dev.to/kleinhouzin/two-allowedhosts-every-developer-should-know-ehe</link>
      <guid>https://dev.to/kleinhouzin/two-allowedhosts-every-developer-should-know-ehe</guid>
      <description>&lt;p&gt;Whether you’re in .NET, Node.js, Java, or Python — you need to care about what hosts your app trusts.&lt;br&gt;
This is one of those small details that can quietly make or break your app’s security posture.&lt;/p&gt;

&lt;p&gt;And it’s straight out of the OWASP Top 10:&lt;br&gt;
→ A10:2021 – Server-Side Request Forgery (SSRF) and&lt;br&gt;
→ A01:2021 – Broken Access Control.&lt;/p&gt;

&lt;p&gt;Let’s check both sides of “allowed hosts” &lt;/p&gt;


&lt;h2&gt;
  
  
  1️⃣ The Built-in One: Protecting Inbound Traffic
&lt;/h2&gt;

&lt;p&gt;In ASP.NET Core, you’ll often see this in appsettings.json:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "AllowedHosts": "example.com"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That’s not for redirects, API calls, or URLs inside your app.&lt;br&gt;
It’s for incoming HTTP requests — it tells your app which Host headers are allowed.&lt;br&gt;
If someone tries to access your server as &lt;a href="https://evilproxy.com" rel="noopener noreferrer"&gt;https://evilproxy.com&lt;/a&gt;, the request is dropped.&lt;/p&gt;

&lt;p&gt;Think of it as your front door lock 🏠 —&lt;br&gt;
It stops fake domains from pretending to be you.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 Other frameworks have similar controls:&lt;/p&gt;

&lt;p&gt;Express.js → use helmet() or host-validation middleware&lt;/p&gt;

&lt;p&gt;Django → ALLOWED_HOSTS in settings.py&lt;/p&gt;

&lt;p&gt;Spring Boot → server.forward-headers-strategy with a proxy-aware filter&lt;/p&gt;
&lt;/blockquote&gt;


&lt;h2&gt;
  
  
  2️⃣ The Custom One: Protecting Outbound URLs (OWASP SSRF)
&lt;/h2&gt;

&lt;p&gt;Now comes the untold part:&lt;br&gt;
Even if your app’s front door is locked, what about the URLs inside it?&lt;/p&gt;

&lt;p&gt;When users can submit or trigger URLs (for example, a redirect after login, a webhook, or an image fetch), attackers can trick your backend into calling something internal like &lt;a href="http://localhost:8080/admin" rel="noopener noreferrer"&gt;http://localhost:8080/admin&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;That’s Server-Side Request Forgery (SSRF) — and it’s on OWASP’s radar for a reason.&lt;br&gt;
The fix? A custom whitelist middleware that validates every URL before use.&lt;/p&gt;



&lt;p&gt;🧱 Code Example: .NET Middleware to Block Untrusted URLs&lt;/p&gt;

&lt;p&gt;Here’s a simple example in C# — easy to adapt to any stack:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Options;
using System;
using System.Linq;
using System.Threading.Tasks;

public class UrlWhitelistMiddleware
{
    private readonly RequestDelegate _next;
    private readonly string[] _allowedHosts;

    public UrlWhitelistMiddleware(RequestDelegate next, IOptions&amp;lt;SecuritySettings&amp;gt; settings)
    {
        _next = next;
        _allowedHosts = settings.Value.AllowedHosts;
    }

    public async Task InvokeAsync(HttpContext context)
    {
        var returnUrl = context.Request.Query["returnUrl"].ToString();

        if (!string.IsNullOrEmpty(returnUrl) &amp;amp;&amp;amp; !IsAllowed(returnUrl))
        {
            context.Response.StatusCode = 400;
            await context.Response.WriteAsync("Blocked: Untrusted redirect target.");
            return;
        }

        await _next(context);
    }

    private bool IsAllowed(string url)
    {
        if (!Uri.TryCreate(url, UriKind.Absolute, out var uri))
            return false;

        if (uri.Scheme != Uri.UriSchemeHttps &amp;amp;&amp;amp; uri.Scheme != Uri.UriSchemeHttp)
            return false;

        return _allowedHosts.Any(host =&amp;gt;
            uri.Host.Equals(host, StringComparison.OrdinalIgnoreCase) ||
            uri.Host.EndsWith("." + host, StringComparison.OrdinalIgnoreCase));
    }
}

public class SecuritySettings
{
    public string[] AllowedHosts { get; set; } = Array.Empty&amp;lt;string&amp;gt;();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add your whitelist in appsettings.json:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "Security": {
    "AllowedHosts": [ "example.com", "trustedpartner.org" ]
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And register it in your app:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;app.UseMiddleware&amp;lt;UrlWhitelistMiddleware&amp;gt;();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;✅ TL;DR — What Devs Should Remember&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Purpose   Type Example OWASP Relevance&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Inbound host validation  Built-in AllowedHosts   Prevents Host Header Injection  A05:2021&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Security Misconfiguration&lt;br&gt;
Outbound / redirect URL validation  Custom middleware whitelist Prevents SSRF, open redirects   A10:2021 – SSRF&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;🔐 Final Word&lt;/p&gt;

&lt;p&gt;Whether you write in .NET, Node, or Go, make your app paranoid about URLs like you are when clicking on a link received in an email.&lt;br&gt;
A trusted host list is one of the simplest, cheapest, and most effective shields against SSRF and open redirect attacks.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;🧩 Lock the door. Guard the window.&lt;br&gt;
OWASP and Reality has been warning us for years — time to listen, especially devs and software architects.&lt;/p&gt;
&lt;/blockquote&gt;




</description>
      <category>webdev</category>
      <category>csslp</category>
      <category>softwaresecurity</category>
      <category>dotnet</category>
    </item>
    <item>
      <title>🚀 Building Truly Resilient SQL Server Applications in .NET</title>
      <dc:creator>Klein Houzin</dc:creator>
      <pubDate>Thu, 16 Oct 2025 07:16:38 +0000</pubDate>
      <link>https://dev.to/kleinhouzin/building-truly-resilient-sql-server-applications-in-net-3hld</link>
      <guid>https://dev.to/kleinhouzin/building-truly-resilient-sql-server-applications-in-net-3hld</guid>
      <description>&lt;h3&gt;
  
  
  &lt;strong&gt;Introduction&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Modern enterprise systems rarely fail because of code — they fail because of &lt;strong&gt;transient infrastructure conditions&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Whether you’re running on &lt;strong&gt;Azure SQL&lt;/strong&gt;, &lt;strong&gt;SQL Server in Kubernetes&lt;/strong&gt;, or &lt;strong&gt;on-prem clusters&lt;/strong&gt;, you will inevitably face &lt;strong&gt;temporary failures&lt;/strong&gt;: network drops, throttling, deadlocks, DNS hiccups, or resource contention.&lt;br&gt;
These are &lt;em&gt;not permanent faults&lt;/em&gt; — they are part of the system’s natural breathing pattern.&lt;/p&gt;

&lt;p&gt;The key is not to panic, but to &lt;strong&gt;build resilience&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In .NET and Entity Framework Core, this resilience is achieved through &lt;strong&gt;Execution Strategies&lt;/strong&gt; and &lt;strong&gt;configurable retry logic&lt;/strong&gt;.&lt;br&gt;
But here’s the catch: the default retry logic doesn’t always cover every transient condition you’ll encounter in production.&lt;/p&gt;

&lt;p&gt;That’s where extending the &lt;strong&gt;transient error numbers&lt;/strong&gt; becomes crucial.&lt;/p&gt;


&lt;h3&gt;
  
  
  &lt;strong&gt;The Hidden Edge: &lt;code&gt;errorNumbersToAdd&lt;/code&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;When you configure SQL resiliency in .NET, one of the most powerful yet overlooked parameters is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;errorNumbersToAdd&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This parameter allows you to &lt;strong&gt;extend the list of SQL error codes&lt;/strong&gt; that are treated as &lt;em&gt;transient&lt;/em&gt; — meaning, errors that are safe to retry automatically.&lt;/p&gt;

&lt;p&gt;Out of the box, EF Core’s &lt;code&gt;SqlAzureExecutionStrategy&lt;/code&gt; already knows how to handle the common suspects (e.g., &lt;code&gt;40613&lt;/code&gt;, &lt;code&gt;40197&lt;/code&gt;, &lt;code&gt;40501&lt;/code&gt;, etc.).&lt;br&gt;
But in the field, architects often discover additional transient patterns specific to their workloads — deadlocks, resource throttling, or connection resets — that don’t get retried by default.&lt;/p&gt;

&lt;p&gt;If your retry logic doesn’t recognize them, it fails unnecessarily — producing false negatives, failed transactions, and unneeded alerts.&lt;/p&gt;


&lt;h3&gt;
  
  
  &lt;strong&gt;The Architecture of Resilience&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;A well-designed retry mechanism must be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Deterministic&lt;/strong&gt; — only retry on known transient conditions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bounded&lt;/strong&gt; — never retry endlessly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Idempotent&lt;/strong&gt; — safe to re-execute operations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Transparent&lt;/strong&gt; — log every retry attempt for observability.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Extending &lt;code&gt;errorNumbersToAdd&lt;/code&gt; strengthens that architecture by covering real-world transient faults that your database layer may throw.&lt;/p&gt;


&lt;h3&gt;
  
  
  &lt;strong&gt;The Battle-Tested Transient Error Codes&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Here’s a curated list — drawn from real enterprise production systems — of SQL Server and Azure SQL error codes that should &lt;strong&gt;absolutely&lt;/strong&gt; be treated as transient.&lt;/p&gt;

&lt;p&gt;These are the codes you’ll want in your retry configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Network &amp;amp; Connection Failures&lt;/span&gt;
    &lt;span class="m"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;     &lt;span class="c1"&gt;// Fatal error in current connection&lt;/span&gt;
    &lt;span class="m"&gt;53&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;     &lt;span class="c1"&gt;// Cannot open a connection to SQL Server&lt;/span&gt;
    &lt;span class="m"&gt;64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;     &lt;span class="c1"&gt;// Network name deleted&lt;/span&gt;
    &lt;span class="m"&gt;10053&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;// Network connection aborted&lt;/span&gt;
    &lt;span class="m"&gt;10054&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;// Connection reset by peer&lt;/span&gt;
    &lt;span class="m"&gt;10060&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;// Network timeout&lt;/span&gt;
    &lt;span class="m"&gt;11001&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;// DNS lookup failure&lt;/span&gt;
    &lt;span class="m"&gt;17197&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;// SSL / encryption issue under load&lt;/span&gt;

    &lt;span class="c1"&gt;// Resource or Throttling&lt;/span&gt;
    &lt;span class="m"&gt;40197&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;// Azure SQL internal transient error&lt;/span&gt;
    &lt;span class="m"&gt;40501&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;// Throttling (Too many requests)&lt;/span&gt;
    &lt;span class="m"&gt;40549&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;// Session terminated due to transaction timeout&lt;/span&gt;
    &lt;span class="m"&gt;40613&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;// Database unavailable&lt;/span&gt;
    &lt;span class="m"&gt;40615&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;// Database failover in progress&lt;/span&gt;
    &lt;span class="m"&gt;10928&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;// Resource limit reached&lt;/span&gt;
    &lt;span class="m"&gt;10929&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;// Resource throttling&lt;/span&gt;
    &lt;span class="m"&gt;10936&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;// Resource governor limit&lt;/span&gt;

    &lt;span class="c1"&gt;// Concurrency&lt;/span&gt;
    &lt;span class="m"&gt;1205&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="c1"&gt;// Deadlock victim&lt;/span&gt;

    &lt;span class="c1"&gt;// Login / Session Availability&lt;/span&gt;
    &lt;span class="m"&gt;233&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;    &lt;span class="c1"&gt;// Connection initialization failed&lt;/span&gt;
    &lt;span class="m"&gt;18401&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;// Login failed: database unavailable&lt;/span&gt;
    &lt;span class="m"&gt;18456&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;// Login failed for user (transient in Azure)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These numbers cover the &lt;strong&gt;real surface of transient volatility&lt;/strong&gt; — from network oscillations to throttling and failover events.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;How to Apply Them in EF Core&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;In your &lt;code&gt;Program.cs&lt;/code&gt; or &lt;code&gt;Startup.cs&lt;/code&gt;, configure your DbContext like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddDbContext&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;AppDbContext&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UseSqlServer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;connectionString&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;sqlOptions&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;sqlOptions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ExecutionStrategy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;deps&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
                &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;SqlAzureExecutionStrategy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                    &lt;span class="n"&gt;dependencies&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;deps&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;maxRetryCount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;maxRetryDelay&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;TimeSpan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;FromSeconds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                    &lt;span class="n"&gt;errorNumbersToAdd&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;
                    &lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="m"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;53&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;10053&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;10054&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;10060&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;11001&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;17197&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="m"&gt;40197&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;40501&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;40549&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;40613&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;40615&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="m"&gt;10928&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;10929&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;10936&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="m"&gt;1205&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;233&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;18401&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;18456&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="p"&gt;}));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, when your application encounters these errors, &lt;strong&gt;EF Core automatically retries&lt;/strong&gt; the operation before surfacing an exception.&lt;br&gt;
That’s production-grade resilience with minimal code.&lt;/p&gt;


&lt;h3&gt;
  
  
  &lt;strong&gt;Advanced Option — Unified Retry Policy&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Architects managing both EF and raw ADO.NET calls can centralize retry configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SqlRetryPolicy&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;AdditionalTransientErrors&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="m"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;53&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;10053&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;10054&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;10060&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;11001&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;17197&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="m"&gt;40197&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;40501&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;40549&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;40613&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;40615&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="m"&gt;10928&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;10929&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;10936&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="m"&gt;1205&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;233&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;18401&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;18456&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;SqlRetryLogicBaseProvider&lt;/span&gt; &lt;span class="nf"&gt;CreateProvider&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;SqlRetryLogicOption&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;NumberOfTries&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;DeltaTime&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;TimeSpan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;FromSeconds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="n"&gt;MaxTimeInterval&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;TimeSpan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;FromSeconds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="n"&gt;AdditionalErrorNumbers&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;HashSet&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;AdditionalTransientErrors&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="n"&gt;SqlConfigurableRetryFactory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateFixedRetryProvider&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;options&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then apply it to both ADO.NET connections and EF contexts — a single source of truth for retry logic across your stack.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Key Lessons for Architects&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Know your environment.&lt;/strong&gt; Azure SQL behaves differently under throttling than on-prem SQL Server. Observe which errors are transient in your setup.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Log intelligently.&lt;/strong&gt; Retrying hides transient faults, but you still need visibility. Instrument retry events through structured logging.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Avoid over-retrying.&lt;/strong&gt; Retrying too aggressively under heavy load can worsen the problem. Respect backoff intervals.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Protect idempotency.&lt;/strong&gt; Only retry operations that can safely be re-executed. Avoid side-effect–heavy business logic in the same transaction scope.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Conclusion&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Resilience isn’t just about writing “retry code.” It’s about &lt;strong&gt;understanding the system’s failure modes&lt;/strong&gt; and &lt;strong&gt;engineering your software to breathe with them&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;By extending &lt;code&gt;errorNumbersToAdd&lt;/code&gt; with the right SQL error codes, you move from reactive error handling to &lt;em&gt;architectural fault tolerance&lt;/em&gt;.&lt;br&gt;
Your systems stop failing for the wrong reasons — and start recovering automatically from the right ones.&lt;/p&gt;

&lt;p&gt;That’s what separates &lt;em&gt;good systems&lt;/em&gt; from &lt;em&gt;great architectures&lt;/em&gt;.&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>programming</category>
      <category>webdev</category>
      <category>sqlserver</category>
    </item>
    <item>
      <title>Channels in .NET 8</title>
      <dc:creator>Klein Houzin</dc:creator>
      <pubDate>Mon, 06 Oct 2025 09:02:50 +0000</pubDate>
      <link>https://dev.to/kleinhouzin/channels-in-net-8-4hog</link>
      <guid>https://dev.to/kleinhouzin/channels-in-net-8-4hog</guid>
      <description>&lt;p&gt;In .NET Core, &lt;strong&gt;&lt;code&gt;System.Threading.Channels&lt;/code&gt;&lt;/strong&gt; are preferred over classic queues like &lt;code&gt;ConcurrentQueue&amp;lt;T&amp;gt;&lt;/code&gt; for high-performance producer–consumer scenarios. Here’s why &lt;code&gt;Channel&lt;/code&gt; is better in all your implementations instead of a traditional &lt;code&gt;Queue&lt;/code&gt; or &lt;code&gt;ConcurrentQueue&lt;/code&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  1. Channels are purpose-built for asynchronous producer–consumer workflows
&lt;/h3&gt;

&lt;p&gt;A &lt;code&gt;Channel&amp;lt;T&amp;gt;&lt;/code&gt; provides both:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a &lt;strong&gt;writer&lt;/strong&gt; for producers (e.g., code that enqueues HTTP requests), and&lt;/li&gt;
&lt;li&gt;a &lt;strong&gt;reader&lt;/strong&gt; for consumers (background workers processing those requests).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Unlike a regular queue, a &lt;code&gt;Channel&lt;/code&gt; natively supports:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;asynchronous writes and reads&lt;/strong&gt; (&lt;code&gt;WriteAsync&lt;/code&gt;, &lt;code&gt;ReadAsync&lt;/code&gt;),&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;backpressure&lt;/strong&gt; (bounded capacity), and&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;completion signaling&lt;/strong&gt; (knowing when no more items will arrive).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This matches exactly what a background HTTP queue needs.&lt;/p&gt;




&lt;h3&gt;
  
  
  2. Built-in backpressure (bounded capacity)
&lt;/h3&gt;

&lt;p&gt;When using &lt;code&gt;Channel.CreateBounded&amp;lt;T&amp;gt;()&lt;/code&gt;, you can specify a maximum capacity and a policy for what happens when it’s full:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;Channel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CreateBounded&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;RequestJob&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;BoundedChannelOptions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;5000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;FullMode&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BoundedChannelFullMode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Wait&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This prevents unbounded memory growth when producers enqueue faster than consumers can process. A normal queue would keep growing until memory runs out.&lt;/p&gt;




&lt;h3&gt;
  
  
  3. Non-blocking async operations
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;Channel&amp;lt;T&amp;gt;&lt;/code&gt; integrates with &lt;code&gt;async/await&lt;/code&gt;. Writers can &lt;code&gt;await channel.Writer.WriteAsync()&lt;/code&gt; and yield control instead of blocking threads. Readers can &lt;code&gt;await channel.Reader.ReadAsync()&lt;/code&gt; to efficiently wait for new items. This is ideal for background services in ASP.NET Core, which should be &lt;strong&gt;non-blocking and cooperative&lt;/strong&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  4. Thread safety without locking
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;Channel&amp;lt;T&amp;gt;&lt;/code&gt; is fully thread-safe and internally optimized for multiple writers and readers. Unlike manual queue + lock approaches, Channels avoid lock contention and use lock-free algorithms where possible.&lt;/p&gt;




&lt;h3&gt;
  
  
  5. Graceful shutdown support
&lt;/h3&gt;

&lt;p&gt;When the hosted service stops, the channel can be &lt;strong&gt;completed&lt;/strong&gt; or &lt;strong&gt;cancelled&lt;/strong&gt;, letting readers finish processing remaining jobs. This helps with controlled termination:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;_channel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Writer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Complete&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;_channel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Reader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ReadAllAsync&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With a classic queue, you’d have to invent your own shutdown signaling.&lt;/p&gt;




&lt;h3&gt;
  
  
  6. Integration with async streams
&lt;/h3&gt;

&lt;p&gt;Channels expose an &lt;code&gt;IAsyncEnumerable&amp;lt;T&amp;gt;&lt;/code&gt; via &lt;code&gt;ReadAllAsync()&lt;/code&gt;. This allows idiomatic streaming loops like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;job&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Reader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ReadAllAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ct&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;Process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;job&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;This syntax is clean, safe, and natively supports cancellation.&lt;/p&gt;




&lt;h3&gt;
  
  
  7. Designed for high throughput
&lt;/h3&gt;

&lt;p&gt;Channels are implemented in highly optimized C# and use efficient internal buffers. Benchmarks show Channels outperform many manual queue + semaphore implementations for async workloads.&lt;/p&gt;




&lt;h3&gt;
  
  
  Summary Table
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Channel&lt;/th&gt;
&lt;th&gt;ConcurrentQueue&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Async writes/reads&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bounded capacity&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Backpressure&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Graceful shutdown&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;⚠ (manual)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Lock-free concurrency&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Integrated with async streams&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h3&gt;
  
  
  In short
&lt;/h3&gt;

&lt;p&gt;Using &lt;code&gt;Channel&amp;lt;T&amp;gt;&lt;/code&gt; makes your class:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;safer (no manual thread signaling),&lt;/li&gt;
&lt;li&gt;more memory-efficient (bounded queues), and&lt;/li&gt;
&lt;li&gt;naturally asynchronous (no blocking threads).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This aligns perfectly with .NET 8 background service patterns and Microsoft’s modern async design guidance.&lt;/p&gt;

&lt;p&gt;Next time, we will talk about &lt;/p&gt;

</description>
      <category>programming</category>
      <category>dotnet</category>
      <category>dotnetcore</category>
      <category>performance</category>
    </item>
  </channel>
</rss>
