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:

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?

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?

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?

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.

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.

🤖 AlgoLassi Assistant Have a question about this tutorial?

Ask AlgoLassi and get an answer plus the tutorials worth studying next.

Ask a question

đŸ’Ŧ Comments

Sign in with Google to publish immediately, or comment anonymously and wait for approval.

Comments will appear here when available.