Using Redis with .NET Aspire: Caching Made Simple
Redis is one of the most common infrastructure dependencies in modern web applications. .NET Aspire makes adding Redis to your solution remarkably straightforward — from spinning up a container in development to injecting properly configured clients into your services.
Adding Redis to the AppHost
In your AppHost's Program.cs, declare a Redis resource:
var builder = DistributedApplication.CreateBuilder(args);
var cache = builder.AddRedis("cache");
var api = builder.AddProject<Projects.MyApi>("api")
.WithReference(cache);
builder.Build().Run();
When you run the AppHost, Aspire pulls the Redis container image and starts it automatically. The connection string is injected into the api project under the name cache.
If you need Redis with persistent storage or a specific version, you can configure the container:
var cache = builder.AddRedis("cache")
.WithImageTag("7.4")
.WithDataVolume("redis-data");
Consuming Redis in Your Service
On the service side, you install the Aspire Redis component NuGet package:
dotnet add package Aspire.StackExchange.Redis
Then register the Redis connection in your Program.cs:
var builder = WebApplication.CreateBuilder(args);
builder.AddServiceDefaults();
builder.AddRedisClient("cache");
The "cache" name must match the resource name you declared in the AppHost. Aspire handles the connection string resolution automatically.
You can now inject IConnectionMultiplexer anywhere in your application:
public class ProductService
{
private readonly IConnectionMultiplexer _redis;
public ProductService(IConnectionMultiplexer redis)
{
_redis = redis;
}
public async Task<string?> GetCachedProductAsync(int id)
{
var db = _redis.GetDatabase();
return await db.StringGetAsync($"product:{id}");
}
public async Task SetCachedProductAsync(int id, string json)
{
var db = _redis.GetDatabase();
await db.StringSetAsync($"product:{id}", json, TimeSpan.FromMinutes(5));
}
}
Using Redis for Distributed Caching
If you prefer the IDistributedCache abstraction over the raw StackExchange.Redis API, Aspire has a dedicated component:
dotnet add package Aspire.StackExchange.Redis.DistributedCaching
Register it in your service:
builder.AddRedisDistributedCache("cache");
Now you can inject IDistributedCache and use it with the standard API:
public class CatalogController : ControllerBase
{
private readonly IDistributedCache _cache;
private readonly CatalogContext _db;
public CatalogController(IDistributedCache cache, CatalogContext db)
{
_cache = cache;
_db = db;
}
[HttpGet("{id}")]
public async Task<IActionResult> GetProduct(int id)
{
var cacheKey = $"product:{id}";
var cached = await _cache.GetStringAsync(cacheKey);
if (cached is not null)
return Ok(JsonSerializer.Deserialize<Product>(cached));
var product = await _db.Products.FindAsync(id);
if (product is null)
return NotFound();
await _cache.SetStringAsync(cacheKey, JsonSerializer.Serialize(product),
new DistributedCacheEntryOptions
{
AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(10)
});
return Ok(product);
}
}
Output Caching with Redis
Aspire also supports Redis-backed output caching:
dotnet add package Aspire.StackExchange.Redis.OutputCaching
builder.AddRedisOutputCache("cache");
Then apply output caching to endpoints:
app.MapGet("/products", async (CatalogContext db) =>
await db.Products.ToListAsync())
.CacheOutput(policy => policy.Expire(TimeSpan.FromMinutes(5)));
Health Checks and Telemetry
The Aspire Redis components register health checks automatically. The dashboard will show whether the Redis connection is healthy, and you can query the /health endpoint to verify programmatically.
Telemetry is also wired up by default. Redis commands appear as spans in your distributed traces, so you can see cache hit/miss patterns and command latencies directly in the Aspire dashboard.
Configuration Options
You can fine-tune the Redis connection through configuration:
{
"Aspire": {
"StackExchange": {
"Redis": {
"cache": {
"ConfigurationOptions": {
"ConnectTimeout": 5000,
"AbortOnConnectFail": false
},
"DisableHealthChecks": false,
"DisableTracing": false
}
}
}
}
}
Or configure it in code:
builder.AddRedisClient("cache", settings =>
{
settings.ConfigurationOptions.ConnectTimeout = 5000;
settings.DisableHealthChecks = false;
});
The Aspire Redis component removes all the boilerplate of managing Redis connections, health checks, and telemetry. You declare the resource, reference it, and start using it — Aspire handles the rest.