Diagram of the lifetimes

Using Scoped or Singleton Lifetimes for Caching Purposes

Caching is a common requirement in web applications: let’s look at why we would use a Scoped or Singleton lifetime depending on use cases.

Which to choose? It all depends on the scope and duration of the cache’s validity.

Let’s me explain a little bit when to use Scoped lifetime and when to use the Singleton lifetime in this new article.

Caching per Request (Scoped Lifetime)

What are the use cases for the Scoped lifetime?

  • Request-Specific Data: Caching data that is specific to a single request and should not persist beyond that request.
  • Avoiding Repeated Computations: If certain computations or data retrievals are expensive and the result is needed multiple times within the same request, caching within the request’s scope can save resources.

What are real-life examples?

  1. Database Queries: If a particular database query is performed multiple times during a single request and the result is the same, caching the result within the request can improve performance.
  2. User Permissions: Caching the permissions of a user for the duration of a request can avoid repeated checks against an authorization service.

It could be implemented as follows:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public interface IRequestCache
{
    object Get(string key);
    void Set(string key, object value);
}

public class RequestCache : IRequestCache
{
    private readonly IDictionary<string, object> _cache = new Dictionary<string, object>();

    public object Get(string key)
    {
        _cache.TryGetValue(key, out var value);
        return value;
    }

    public void Set(string key, object value)
    {
        _cache[key] = value;
    }
}

// Registering the service in Program.cs
services.AddScoped<IRequestCache, RequestCache>();

Caching per Application Lifetime

What are the use cases for the Singleton lifetime?

  • Global or Shared Data: Caching data that is shared across multiple requests and does not change frequently.
  • Expensive Operations: Data that is expensive to fetch or compute, and should be reused across different requests to avoid repeated overhead.

What are real-life examples?

  1. Configuration Data: Application-wide configuration settings that are loaded once and used throughout the application’s lifetime.
  2. Static Data: Reference data that does not change often, such as country lists or product categories.

It could be implemented as follows:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public interface IGlobalCache
{
    object Get(string key);
    void Set(string key, object value);
}

public class GlobalCache : IGlobalCache
{
    private readonly IDictionary<string, object> _cache = new Dictionary<string, object>();

    public object Get(string key)
    {
        _cache.TryGetValue(key, out var value);
        return value;
    }

    public void Set(string key, object value)
    {
        _cache[key] = value;
    }
}

// Registering the service
services.AddSingleton<IGlobalCache, GlobalCache>();

Conclusion

While both scoped and singleton lifetimes have their use cases for caching, the choice depends on the nature of the data and the requirements of your application.

Scoped caching is less common than singleton caching but is useful for request-specific data that needs to be reused within a single request.

Singleton caching is more common for data that is shared and relatively static across the entire application.

Sources

You can read more from the following resources:

  1. Microsoft Documentation:
  2. Microsoft Learn Module:
    • Dependency injection in .NET
    • This module provides an in-depth look at dependency injection in .NET, including examples and best practices for using different service lifetimes.
  3. Stack Overflow:

Follow me

Thanks for reading this article. Make sure to follow me on X, subscribe to my Substack publication and bookmark my blog to read more in the future.

Licensed under CC BY-NC-SA 4.0
License GPLv3 | Terms
Built with Hugo
Theme Stack designed by Jimmy