Phase 18 of 30 · Topic 18.1

Service Lifetimes: Transient vs Scoped vs Singleton

1Concept

`Transient` creates a new instance on every injection. `Scoped` creates one instance per HTTP request scope. `Singleton` creates a single shared instance across the entire application process lifetime.

2Architecture Diagram

HTTP Request 1 ──> [ Scoped Service A (Instance 1) ] ──> Disposed on Request End
HTTP Request 2 ──> [ Scoped Service A (Instance 2) ] ──> Disposed on Request End
Both Requests  ──> [ Singleton Service B (Shared Instance 1) ] ──> Lives forever

3Code Example

C# 13 & .NET 9
using System;
using Microsoft.Extensions.DependencyInjection;

public interface IOperation { Guid Id { get; } }
public class TransientOp : IOperation { public Guid Id { get; } = Guid.NewGuid(); }
public class SingletonOp : IOperation { public Guid Id { get; } = Guid.NewGuid(); }

public class DiLifetimesDemo
{
    public static void Main()
    {
        var services = new ServiceCollection();
        services.AddTransient<TransientOp>();
        services.AddSingleton<SingletonOp>();

        var provider = services.BuildServiceProvider();

        Console.WriteLine($"Transient 1: {provider.GetRequiredService<TransientOp>().Id}");
        Console.WriteLine($"Transient 2: {provider.GetRequiredService<TransientOp>().Id} (Different!)");

        Console.WriteLine($"Singleton 1: {provider.GetRequiredService<SingletonOp>().Id}");
        Console.WriteLine($"Singleton 2: {provider.GetRequiredService<SingletonOp>().Id} (Identical!)");
    }
}

4Expected Output

Transient 1: d3b07384-d113-4a3e-b83b-9a8c16027a01
Transient 2: 7f8a91c2-3e4b-4a5c-9d6e-8b1a2c3d4e5f (Different!)
Singleton 1: a1b2c3d4-e5f6-4a5b-8c9d-0e1f2a3b4c5d
Singleton 2: a1b2c3d4-e5f6-4a5b-8c9d-0e1f2a3b4c5d (Identical!)

5Key Takeaways

  • Entity Framework DbContext must always be registered as `Scoped`.
  • Singletons must be 100% thread-safe.
  • Transient services should be lightweight without holding unmanaged resources.