Affected
Affected: .NET server-side SDK (all versions when using Microsoft dependency injection)
Overview
When you register the LaunchDarkly .NET client with Microsoft dependency injection (DI), you must use a factory delegate so that only one LdClient instance is created and shared. Registering a pre-created instance with AddSingleton<ILdClient>(new LdClient(...)) can create a new SDK instance every time the registration runs. That leads to many streaming connections, higher than expected service connection counts, and connections that are not disposed when the application shuts down.
This article describes the correct way to register LdClient as a singleton.
Solution
Avoid passing a pre-created instance
Do not register the client by passing an already-constructed instance to AddSingleton. The new LdClient(...) expression runs when the line runs, so every time this registration executes (for example, from multiple layers of abstraction or each time a task sets up dependencies), a new LdClient is created.
Additionally, when you register a pre-created instance, Microsoft DI does not own that instance and does not dispose it when the ServiceProvider or host is disposed.
Incorrect registration:
services.AddSingleton<ILdClient>(new LdClient(appSettings.LaunchDarklyKey))
Register using a factory delegate
Register ILdClient with a factory delegate so that the DI container creates exactly one instance and disposes it when the application shuts down.
- In your service registration (for example, in
Program.csorStartup.cs), callAddSingletonwith a delegate that receives the service provider and returns a newLdClient. - Use your SDK key (or configuration) inside the delegate. The delegate runs only when the first consumer requests
ILdClient, so only one instance is created.
Correct registration:
services.AddSingleton<ILdClient>(provider => new LdClient(appSettings.LaunchDarklyKey));
With this pattern, the DI container creates the instance, holds the single reference, and disposes it when the ServiceProvider or host is disposed.
Use this pattern even if you believe AddSingleton is only called once in your codebase. It is the correct approach and helps avoid multiple instances if your registration is ever invoked more than once (for example, from shared setup code used by many tasks or services).