What is the overhead of creating a new HttpClient per call in a WebAPI client? What is the overhead of creating a new HttpClient per call in a WebAPI client? asp.net asp.net

What is the overhead of creating a new HttpClient per call in a WebAPI client?


HttpClient has been designed to be re-used for multiple calls. Even across multiple threads.The HttpClientHandler has Credentials and Cookies that are intended to be re-used across calls. Having a new HttpClient instance requires re-setting up all of that stuff.Also, the DefaultRequestHeaders property contains properties that are intended for multiple calls. Having to reset those values on each request defeats the point.

Another major benefit of HttpClient is the ability to add HttpMessageHandlers into the request/response pipeline to apply cross cutting concerns. These could be for logging, auditing, throttling, redirect handling, offline handling, capturing metrics. All sorts of different things. If a new HttpClient is created on each request, then all of these message handlers need to be setup on each request and somehow any application level state that is shared between requests for these handlers also needs to be provided.

The more you use the features of HttpClient, the more you will see that reusing an existing instance makes sense.

However, the biggest issue, in my opinion is that when a HttpClient class is disposed, it disposes HttpClientHandler, which then forcibly closes the TCP/IP connection in the pool of connections that is managed by ServicePointManager. This means that each request with a new HttpClient requires re-establishing a new TCP/IP connection.

From my tests, using plain HTTP on a LAN, the performance hit is fairly negligible. I suspect this is because there is an underlying TCP keepalive that is holding the connection open even when HttpClientHandler tries to close it.

On requests that go over the internet, I have seen a different story. I have seen a 40% performance hit due to having to re-open the request every time.

I suspect the hit on a HTTPS connection would be even worse.

My advice is to keep an instance of HttpClient for the lifetime of your application for each distinct API that you connect to.


If you want your application to scale, the difference is HUGE! Depending on the load, you will see very different performance numbers. As Darrel Miller mentions, the HttpClient was designed to be re-used across requests. This was confirmed by folks on the BCL team who wrote it.

A recent project I had was to help a very large and well-known online computer retailer scale out for Black Friday/holiday traffic for some new systems. We ran into some performance issues around the usage of HttpClient. Since it implements IDisposable, the devs did what you would normally do by creating an instance and placing it inside of a using() statement. Once we started load testing the app brought the server to its knees - yes, the server not just the app. The reason is that every instance of HttpClient opens a port on the server. Because of non-deterministic finalization of GC and the fact that you are working with computer resources that span across multiple OSI layers, closing network ports can take a while. In fact Windows OS itself can take up to 20 secs to close a port (per Microsoft). We were opening ports faster than they could be closed - server port exhaustion which hammered the CPU to 100%. My fix was to change the HttpClient to a static instance which solved the problem. Yes, it is a disposable resource, but any overhead is vastly outweighed by the difference in performance. I encourage you to do some load testing to see how your app behaves.

You can also check out the WebAPI Guidance page for documentation and example athttps://www.asp.net/web-api/overview/advanced/calling-a-web-api-from-a-net-client

Pay special attention to this call-out:

HttpClient is intended to be instantiated once and re-used throughout the life of an application. Especially in server applications, creating a new HttpClient instance for every request will exhaust the number of sockets available under heavy loads. This will result in SocketException errors.

If you find that you need to use a static HttpClient with different headers, base address, etc. what you will need to do is to create the HttpRequestMessage manually and set those values on the HttpRequestMessage. Then, use the HttpClient:SendAsync(HttpRequestMessage requestMessage, ...)

UPDATE for .NET Core:You should use the IHttpClientFactory via Dependency Injection to create HttpClient instances. It will manage the lifetime for you and you do not need to explicitly dispose it. See Make HTTP requests using IHttpClientFactory in ASP.NET Core


As the other answers state, HttpClient is meant for reuse. However, reusing a single HttpClient instance across a multi-threaded application means you can't change the values of its stateful properties, like BaseAddress and DefaultRequestHeaders (so you can only use them if they are constant across your application).

One approach for getting around this limitation is wrapping HttpClient with a class that duplicates all the HttpClient methods you need (GetAsync, PostAsync etc) and delegates them to a singleton HttpClient. However that's pretty tedious (you will need to wrap the extension methods too), and fortunately there is another way - keep creating new HttpClient instances, but reuse the underlying HttpClientHandler. Just make sure you don't dispose the handler:

HttpClientHandler _sharedHandler = new HttpClientHandler(); //never dispose thisHttpClient GetClient(string token){    //client code can dispose these HttpClient instances    return new HttpClient(_sharedHandler, disposeHandler: false)             {       DefaultRequestHeaders =        {            Authorization = new AuthenticationHeaderValue("Bearer", token)        }     };}