Lesson 16 / 26
Service Lifetimes
Choose between transient, scoped and singleton and avoid the captive dependency bug.
Three lifetimes
Transient: a new instance every time. Scoped: one instance per HTTP request. Singleton: one instance for the whole app. Database contexts are scoped; stateless helpers and caches are often singletons.
Registering each lifetime
Pick the shortest lifetime that works. A singleton must be thread-safe because many requests share it.
builder.Services.AddTransient<IIdGenerator, IdGenerator>();
builder.Services.AddScoped<IOrderService, OrderService>();
builder.Services.AddSingleton<IClock, SystemClock>();Captive dependency
A singleton must not hold a scoped service such as DbContext: it would keep one request's instance alive forever. In development, scope validation catches this at startup.
Quick check: How many instances of a scoped service exist during one HTTP request?
- A new one per use
- Zero
- One
- One per thread forever
Answer
One — Scoped services are created once per request scope and shared within it.