ASP.NET Core · Service lifetimes

ASP.NET Core dependency injection interview questions

Service registration is only the beginning. Explain who owns each instance, how long it lives, and what happens when requests share it.

Published by RoleHello. Technical references are linked below.

How do transient, scoped, and singleton services differ?

A transient registration creates an instance each time the container resolves it. A scoped registration reuses one instance within a scope, usually an HTTP request in ASP.NET Core. A singleton registration shares one instance across the application container.

Choose a lifetime around ownership and state. A request-specific unit of work usually belongs in a scope. A shared service must safely handle concurrent callers. Registration lifetime alone does not make its fields thread-safe.

Why is a scoped dependency inside a singleton a problem?

The singleton keeps the dependency longer than its intended scope. This is a captive dependency: request-specific state or disposable resources can escape their lifetime. Scope validation can detect invalid resolutions, but disabling it does not fix the design.

For example, a singleton report scheduler should not hold a request’s database context in a constructor field. Decide where a report starts and ends, then make the context’s ownership match that unit of work.

How does a background service use scoped dependencies?

A hosted background service has no automatic scope for each job. Inject IServiceScopeFactory and create a scope around a unit of work. Resolve the scoped processor inside it and await completion before disposal:

// One job inside a BackgroundService; scopeFactory is injected.
await using var scope = scopeFactory.CreateAsyncScope();
var processor = scope.ServiceProvider.GetRequiredService<JobProcessor>();
await processor.ProcessAsync(stoppingToken);

Register JobProcessor as scoped. Do not start unawaited work that continues using it after this block exits. For parallel jobs, use separate scopes so their mutable scoped dependencies are not accidentally shared.

Does transient mean that an object is immediately disposed?

No. A container-created disposable service is managed by the container that owns it. Transient describes creation frequency; it does not promise disposal immediately after a method call. Pay attention to where services are resolved, especially from the root provider.

Prefer constructor injection in application services so required dependencies are visible. Keep explicit scope creation at boundaries such as background job processing.

Try explaining this scenario

A cache is shared across all users and stores a current user’s permissions in a field. Would changing its registration to scoped solve the whole problem? Explain the intended cache key, whether values belong to one user, how permissions expire, and whether concurrent requests can corrupt state. A lifetime change cannot replace those decisions.

Technical references