Singleton vs Scoped vs Transient in ASP.NET Core: What's the Difference?
When working with Dependency Injection in ASP.NET Core, you will frequently encounter three service lifetimes: Singleton, Scoped, and Transient.
These lifetimes determine how long an instance of a registered service remains available and when a new instance should be created.
What Are Service Lifetimes?
A service lifetime defines how the ASP.NET Core Dependency Injection container manages instances of a service.
ASP.NET Core provides three main service lifetimes:
- Singleton â One instance is created for the entire application.
- Scoped â One instance is created per request/scope.
- Transient â A new instance is created every time the service is requested.
1. Singleton
A Singleton service is created only once and the same instance is reused throughout the lifetime of the application.
builder.Services.AddSingleton<IMyService, MyService>();
When should you use Singleton?
- Configuration or application-wide services
- Stateless services that are safe to share
- Expensive objects that can safely be reused
- Application-wide caching
2. Scoped
A Scoped service creates one instance for each scope. In a typical ASP.NET Core web application, a scope normally corresponds to an HTTP request.
builder.Services.AddScoped<IMyService, MyService>();
If the same service is requested multiple times during one HTTP request, the same instance is returned.
When should you use Scoped?
- Database-related services
- Entity Framework Core DbContext
- Services that should live for one HTTP request
- Request-specific state
3. Transient
A Transient service creates a new instance every time the service is requested from the Dependency Injection container.
builder.Services.AddTransient<IMyService, MyService>();
When should you use Transient?
- Lightweight stateless services
- Services that do not maintain state
- Short-lived operations
Singleton vs Scoped vs Transient
| Lifetime | Instance Created | Typical Usage |
|---|---|---|
| Singleton | Once for the application | Application-wide services |
| Scoped | Once per request/scope | DbContext and request services |
| Transient | Every time requested | Lightweight stateless services |
Example
You can register all three service lifetimes in the
Program.cs file:
builder.Services.AddSingleton<ISingletonService, SingletonService>();
builder.Services.AddScoped<IScopedService, ScopedService>();
builder.Services.AddTransient<ITransientService, TransientService>();
Which Lifetime Should You Choose?
The correct lifetime depends on how your service should behave.
- Choose Singleton when one shared instance should exist for the entire application.
- Choose Scoped when the service should have one instance per request or scope.
- Choose Transient when a fresh instance should be created whenever the service is requested.
Important: Avoid Captive Dependencies
One important rule is that a Singleton should not directly depend on a Scoped service. This can cause a lifetime mismatch known as a captive dependency.
For example, injecting a Scoped service directly into a Singleton can cause the scoped service to live much longer than intended.
Conclusion
Singleton, Scoped, and Transient are the three fundamental service lifetimes in ASP.NET Core Dependency Injection.
Understanding these lifetimes is important because choosing the wrong lifetime can lead to unexpected behavior, excessive object creation, memory usage, or incorrect state sharing.
As a general rule, use Scoped for request-based services, Transient for lightweight stateless services, and Singleton only when sharing one application-wide instance is appropriate.
Ask AlgoLassi and get an answer plus the tutorials worth studying next.
đŦ Comments
Sign in with Google to publish immediately, or comment anonymously and wait for approval.
Comments will appear here when available.