Service lifetimes in ASP.NET Core (Scoped, Transient, Singleton) and how they behave during an HTTP request. Let me break it down clearly.

Service Lifetimes, ASP.NET Core has three main lifetimes when you register services in the DI container:

LifetimeDescriptionBehavior
Transientservices.AddTransient<T>()A new instance is created every time the service is requested from the container.
Scopedservices.AddScoped<T>()One instance is created per HTTP request. All components in the same request share the same instance.
Singletonservices.AddSingleton<T>()One instance is created once and reused for the entire application lifetime.

builder.Services.AddScoped<IMyScopedService, MyScopedService>();
builder.Services.AddTransient<IMyTransientService, MyTransientService>();

Scoped Service:

  • Created once per HTTP request.
  • If multiple controllers or services in the same request ask for it, they get the same instance.
  • Example: tracking request-specific data (like a user session or DB context).

Transient Service:

  • Created every time it’s injected.
  • Even in the same HTTP request, each injection gets a new instance.
  • Example: lightweight, stateless services.

Example

public class MyController : ControllerBase
{
    private readonly IMyScopedService _scopedService;
    private readonly IMyTransientService _transientService;

    public MyController(IMyScopedService scopedService, IMyTransientService transientService)
    {
        _scopedService = scopedService;
        _transientService = transientService;
    }

    [HttpGet("test")]
    public IActionResult Test()
    {
        var id1 = _scopedService.InstanceId;
        var id2 = _scopedService.InstanceId; // Same as id1 (scoped)

        var t1 = _transientService.InstanceId;
        var t2 = _transientService.InstanceId; // Different from t1 (transient)

        return Ok(new { Scoped1 = id1, Scoped2 = id2, Transient1 = t1, Transient2 = t2 });
    }
}

{
  "Scoped1": "c5a1f1b2",
  "Scoped2": "c5a1f1b2",
  "Transient1": "a2b3c4d5",
  "Transient2": "e6f7g8h9"
}

Scoped: same ID for the same request.

Transient: new ID each time.