Caching in C#: Redis, Memcached, and Built-in Solutions from A to Z

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Introduction: Why Caching is a Critical Component of C# Applications

\n\n

In modern web development, application performance directly impacts user experience and business metrics. Every second of page load delay can cost you 7% of conversions. Caching in C# (.NET) is not just a "nice option" but a mandatory tool for any serious developer.

\n\n

In this article, we will cover three main approaches to caching in the .NET ecosystem: Redis, Memcached, and built-in solutions (MemoryCache). You will learn when to use which tool, how to properly configure the cache, and how to avoid common mistakes. The material will be useful for both beginner C# developers and experienced engineers looking to systematize their knowledge.

\n\n

1. Built-in Caching: MemoryCache and IDistributedCache

\n\n

The .NET platform provides developers with several built-in caching mechanisms that do not require installing third-party services.

\n\n

1.1 MemoryCache — Local Cache for a Single Server

\n\n

IMemoryCache is the simplest and fastest way to cache data in C#. Data is stored in the RAM of the current process. It is ideal for single-threaded applications or applications running on a single server.

\n\n
using Microsoft.Extensions.Caching.Memory;\n\npublic class ProductService\n{\n    private readonly IMemoryCache _cache;\n    \n    public ProductService(IMemoryCache cache)\n    {\n        _cache = cache;\n    }\n\n    public async Task<Product> GetProductAsync(int id)\n    {\n        string cacheKey = $"product_{id}";\n        \n        if (!_cache.TryGetValue(cacheKey, out Product product))\n        {\n            // Expensive operation (e.g., database query)\n            product = await GetProductFromDatabaseAsync(id);\n            \n            var cacheOptions = new MemoryCacheEntryOptions()\n                .SetAbsoluteExpiration(TimeSpan.FromMinutes(30))\n                .SetSlidingExpiration(TimeSpan.FromMinutes(5))\n                .SetSize(1);\n            \n            _cache.Set(cacheKey, product, cacheOptions);\n        }\n        \n        return product;\n    }\n}
\n\n

Key Features of MemoryCache:

\n
    \n
  • High speed — data is read directly from RAM
  • \n
  • No serialization — stores objects as-is
  • \n
  • Limitation — does not work in a server farm (each server has its own cache)
  • \n
  • Risk — the cache is completely cleared when the application restarts
  • \n
\n\n

1.2 IDistributedCache — Abstraction for Distributed Cache

\n\n

The IDistributedCache interface provides a unified API for working with any distributed cache. You can switch between Redis, SQL Server, or NCache without changing business logic code.

\n\n
using Microsoft.Extensions.Caching.Distributed;\nusing System.Text.Json;\n\npublic class WeatherService\n{\n    private readonly IDistributedCache _cache;\n    \n    public WeatherService(IDistributedCache cache)\n    {\n        _cache = cache;\n    }\n\n    public async Task<WeatherForecast> GetForecastAsync(string city)\n    {\n        string cacheKey = $"weather_{city}";\n        string cachedData = await _cache.GetStringAsync(cacheKey);\n        \n        if (cachedData != null)\n        {\n            return JsonSerializer.Deserialize<WeatherForecast>(cachedData);\n        }\n        \n        var forecast = await FetchFromApiAsync(city);\n        var serialized = JsonSerializer.Serialize(forecast);\n        \n        await _cache.SetStringAsync(cacheKey, serialized, new DistributedCacheEntryOptions\n        {\n            AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(15)\n        });\n        \n        return forecast;\n    }\n}
\n\n

2. R

Blogs

Book Recommendations