Advanced Caching in C#: Redis, Memcached, and Built-in Solutions

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 Advanced Caching Changes Everything

In modern high-load architecture, response speed and reducing database load are key tasks. Caching in C# (.NET) is no longer just about remembering a result: it is a complex system for managing state, lifetime, and data consistency. At an advanced level, a developer must choose between Redis, Memcached, and built-in solutions depending on the scenario.

In this article, we will analyze three main approaches to caching in the .NET ecosystem, compare their performance, implementation complexity, and common mistakes. You will learn how to set up a distributed cache with Redis, optimize Memcached for high loads, and when the built-in IMemoryCache is the best solution.



Built-in Caching in .NET: IMemoryCache and IDistributedCache

IMemoryCache — Fast Local Cache

The built-in IMemoryCache from the Microsoft.Extensions.Caching.Memory namespace is an ideal solution for a single application instance. It stores data in the process's RAM, providing minimal latency.

// Registration in Startup.cs or Program.csbuilder.Services.AddMemoryCache();

// Usage in a servicepublic class ProductService{ private readonly IMemoryCache _cache;

public ProductService(IMemoryCache cache) { _cache = cache; }

public async Task<Product> GetProductAsync(int id) { string cacheKey = $"product_{id}"; if (!_cache.TryGetValue(cacheKey, out Product product)) { product = await _repository.GetProductByIdAsync(id); var cacheEntryOptions = new MemoryCacheEntryOptions() .SetAbsoluteExpiration(TimeSpan.FromMinutes(5)) .SetSlidingExpiration(TimeSpan.FromMinutes(1)) .SetPriority(CacheItemPriority.High);

_cache.Set(cacheKey, product, cacheEntryOptions); } return product; }}

Pros: zero network latency, easy setup, support for sliding and absolute expiration.

Cons: does not work when scaling to multiple servers; limited by the process's RAM capacity.



IDistributedCache — Abstraction for Distributed Caches

The IDistributedCache interface allows you to easily switch between Redis, SQL Server, or NCache without changing business logic. The default implementation is MemoryDistributedCache (local), but for production, Redis is typically chosen.

// Registering Redis implementationbuilder.Services.AddStackExchangeRedisCache(options =>{    options.Configuration = "localhost:6379";    options.InstanceName = "SampleInstance";});

// Usagepublic async Task SetCacheAsync(string key, byte[] data){ var cache = context.RequestServices.GetRequiredService<IDistributedCache>(); await cache.SetAsync(key, data, new DistributedCacheEntryOptions { AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(1) });}

The key advantage is unification: you write the code once, and the cache provider is changed through configuration.



Redis in C#: Advanced Techniques and Patterns

Connection and Connection Pooling

To work with Redis in .NET, the StackExchange.Redis library is used. Instead of creating a new connection each time, use multiplexing — one connection for the entire application.

// Global singletonpublic static ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("localhost:6379,abortConnect=false");

// Getting the databaseIDatabase db = redis.GetDatabase(0);

// Basic operationsawait db.StringSetAsync("user:1", "John Doe", TimeSpan.FromMinutes(30));string name = await db.StringGetAsync("user:1");

Blogs

Book Recommendations