Fix: HttpClient Socket Exhaustion Error - Dev Fix in 30 Seconds

Published: Jun 04, 2026 · By Kumar Kunal

The Error

System.Net.Sockets.SocketException: Only one usage of each socket address is normally permitted

Quick Fix - 2 Minutes

// BAD: new HttpClient() in loop causes socket exhaustion
// GOOD: Dev Fix using HttpClientFactory .NET 8

// Program.cs builder.Services.AddHttpClient("GitHub", client => { client.BaseAddress = new Uri("https://api.github.com/"); client.DefaultRequestHeaders.Add("User-Agent", "DevFix"); });

// Inject IHttpClientFactory public class GitHubService { private readonly IHttpClientFactory _factory; public GitHubService(IHttpClientFactory factory) => _factory = factory;

public async Task<string> Get() 
{
    var client = _factory.CreateClient("GitHub"); // Reuses handlers
    return await client.GetStringAsync("/");
}

}

Why This Happens

new HttpClient() creates a new socket per instance. Under load, Windows runs out of ports in TIME_WAIT. HttpClientFactory pools handlers and reuses sockets. .NET 8 default handler lifetime is 2 minutes.

Real-World Scenario: Why Singleton HttpClient Still Breaks

Devs "fix" socket exhaustion with static HttpClient, then get DNS issues:

// WRONG: Singleton HttpClient caches DNS forever
public static class ApiClient
{
    private static readonly HttpClient client = new HttpClient(); // BAD
}

// RIGHT: Typed Client with handler rotation // Program.cs builder.Services.AddHttpClient(client => { client.BaseAddress = new Uri("https://api.stripe.com/"); client.Timeout = TimeSpan.FromSeconds(30); }) .SetHandlerLifetime(TimeSpan.FromMinutes(5)); // Dev Fix: Rotate DNS every 5min

// PaymentService.cs public class PaymentService { private readonly HttpClient _client; public PaymentService(HttpClient client) => _client = client; // Injected

public async Task ChargeAsync() => await _client.PostAsync("/charges", null);

}

Why Singleton breaks: HttpClient caches DNS for the lifetime of the handler. If Stripe changes IPs, your static client keeps hitting the old dead IP. SetHandlerLifetime forces DNS refresh. Factory default is 2 minutes.

Related Fixes You Should Know

Socket exhaustion triggers these next:

FAQ

Q: How do I check if I have socket exhaustion?

Run netstat -ano | find "TIME_WAIT" on Windows. If you see thousands of entries to port 443, you're leaking sockets. Or check PerfView for System.Net.Sockets events.

Q: Is using static HttpClient ever OK?

No. Even Microsoft docs say don't. Static HttpClient never refreshes DNS. If your API moves servers, you'll get timeouts until app restart. Use AddHttpClient typed client instead.

Best Practice for .NET 8

  1. Never new HttpClient() - use AddHttpClient() DI
  2. For named clients: _factory.CreateClient("Name")
  3. For typed clients: builder.Services.AddHttpClient()
  4. Singleton HttpClient is wrong too - DNS changes won't refresh
  5. Set handler lifetime: .SetHandlerLifetime(TimeSpan.FromMinutes(5)) if needed

Related Dev Fixes

Found this helpful?

Master C# with our complete course. Real apps, real skills, job-ready in 2 hours.

Share this fix: Twitter LinkedIn

Comments on Fix: HttpClient Socket Exhaustion Error - Dev Fix in 30 Seconds (0)

No comments yet. Be the first to share your thoughts!