Outbound HTTP deserves the same structure as inbound endpoints. If every service manually creates clients, sets headers, chooses timeouts, and wires retry behavior, the application gets inconsistent fast.
Use IHttpClientFactory when your app needs named or typed clients with shared configuration. Put base addresses, default headers, timeouts, authentication handlers, resilience policies, logging, and service-specific behavior in one registration instead of scattering them across call sites.
This also avoids the classic lifecycle traps around HttpClient and handlers. Creating clients casually can lead to socket pressure. Keeping one static client forever can miss DNS changes unless it is configured carefully. The factory gives ASP.NET Core apps a standard place to manage handler lifetime and client configuration.
Keep the HTTP plumbing at startup instead of hiding it inside service classes. With Microsoft.Extensions.Http.Resilience, the same registration can also own the standard resilience pipeline:
builder.Services
.AddHttpClient<IGitHubClient, GitHubClient>(client =>
{
client.BaseAddress = new Uri("https://api.github.com/");
client.DefaultRequestHeaders.UserAgent.ParseAdd("MyApp/1.0");
})
.AddStandardResilienceHandler();
Typed clients are often the cleanest shape. They let the rest of the application depend on a domain-specific service instead of raw HTTP plumbing.
Still set timeouts and cancellation deliberately. IHttpClientFactory gives you a better construction model, not a free reliability strategy. The downstream call still needs clear ownership: what service is called, how long it may take, what failures mean, and whether the caller can retry safely.