StackExchange.Redis.Extensions.Core 12.2.0
StackExchange.Redis.Extensions
StackExchange.Redis.Extensions is a library that extends StackExchange.Redis, making it easier to work with Redis in .NET applications. It wraps the base library with serialization, connection pooling, and higher-level APIs so you can store and retrieve complex objects without writing boilerplate code.
AI-Ready: This library provides an
llms.txtfile for AI coding assistants and a Claude Code plugin for configuration, scaffolding, and troubleshooting.claude plugin add imperugo/StackExchange.Redis.ExtensionsThen use
/redis-configure,/redis-scaffold, or/redis-diagnosein Claude Code.
Features
- Store and retrieve complex .NET objects with automatic serialization
- Multiple serialization providers (System.Text.Json, Newtonsoft, Protobuf, MsgPack, MemoryPack, and more)
- Connection pooling with LeastLoaded and RoundRobin strategies
- Pub/Sub messaging with typed handlers
- Hash operations with per-field expiry (Redis 7.4+)
- GeoSpatial indexes (GEOADD, GEOSEARCH, GEODIST, etc.)
- Redis Streams with consumer group support
- Set, List, and Sorted Set operations
- Key tagging and search
- Transparent compression (GZip, Brotli, LZ4, Snappy, Zstandard)
- Azure Managed Identity support
- ASP.NET Core integration with DI
- Multiple named Redis instances
- OpenTelemetry integration
- .NET Standard 2.1, .NET 8, .NET 9, .NET 10
Architecture
Quick Start
1. Install packages
dotnet add package StackExchange.Redis.Extensions.Core
dotnet add package StackExchange.Redis.Extensions.System.Text.Json
dotnet add package StackExchange.Redis.Extensions.AspNetCore
2. Configure in appsettings.json
{
"Redis": {
"Password": "",
"AllowAdmin": true,
"Ssl": false,
"ConnectTimeout": 5000,
"SyncTimeout": 5000,
"Database": 0,
"Hosts": [
{ "Host": "localhost", "Port": 6379 }
],
"PoolSize": 5,
"IsDefault": true
}
}
3. Register in DI
var redisConfig = builder.Configuration.GetSection("Redis").Get<RedisConfiguration>();
builder.Services.AddStackExchangeRedisExtensions<SystemTextJsonSerializer>(redisConfig);
4. Use it
public class MyService(IRedisDatabase redis)
{
public async Task Example()
{
// Store an object
await redis.AddAsync("user:1", new User { Name = "Ugo", Age = 38 });
// Retrieve it
var user = await redis.GetAsync<User>("user:1");
// Store with expiry
await redis.AddAsync("session:abc", sessionData, TimeSpan.FromMinutes(30));
// Bulk operations
var items = new[]
{
Tuple.Create("key1", "value1"),
Tuple.Create("key2", "value2"),
};
await redis.AddAllAsync(items, TimeSpan.FromHours(1));
// Search keys
var keys = await redis.SearchKeysAsync("user:*");
}
}
NuGet Packages
Core
| Package | Description | NuGet |
|---|---|---|
| Core | Core library with abstractions and implementations | |
| AspNetCore | ASP.NET Core DI integration and middleware |
Serializers (pick one)
Compressors (optional)
Usage Examples
Hash Operations
// Set a hash field
await redis.HashSetAsync("user:1", "name", "Ugo");
await redis.HashSetAsync("user:1", "email", "ugo@example.com");
// Get a hash field
var name = await redis.HashGetAsync<string>("user:1", "name");
// Set with per-field expiry (Redis 7.4+)
await redis.HashSetWithExpiryAsync("user:1", "session", sessionData, TimeSpan.FromMinutes(30));
// Query field TTL
var ttl = await redis.HashFieldGetTimeToLiveAsync("user:1", new[] { "session" });
GeoSpatial
// Add locations
await redis.GeoAddAsync("restaurants", new[]
{
new GeoEntry(13.361389, 38.115556, "Pizzeria Da Michele"),
new GeoEntry(15.087269, 37.502669, "Trattoria del Corso"),
new GeoEntry(12.496366, 41.902782, "Da Enzo al 29"),
});
// Distance between two places
var km = await redis.GeoDistanceAsync("restaurants",
"Pizzeria Da Michele", "Trattoria del Corso", GeoUnit.Kilometers);
// Search within 200km of a point
var nearby = await redis.GeoSearchAsync("restaurants", 13.361389, 38.115556,
new GeoSearchCircle(200, GeoUnit.Kilometers),
count: 10, order: Order.Ascending);
Redis Streams
// Publish typed events
await redis.StreamAddAsync("orders", "payload", new Order { Id = 1, Total = 99.99m });
// Consumer group workflow
await redis.StreamCreateConsumerGroupAsync("orders", "processors");
var entries = await redis.StreamReadGroupAsync("orders", "processors", "worker-1");
foreach (var entry in entries)
{
// Process the message
await redis.StreamAcknowledgeAsync("orders", "processors", entry.Id!);
}
Pub/Sub
// Subscribe to typed messages
await redis.SubscribeAsync<OrderEvent>("orders:new", async order =>
{
Console.WriteLine($"New order: {order.Id}");
});
// Publish
await redis.PublishAsync("orders:new", new OrderEvent { Id = 42 });
Compression
// Enable transparent compression with any serializer
services.AddStackExchangeRedisExtensions<SystemTextJsonSerializer>(config);
services.AddRedisCompression<LZ4Compressor>(); // That's it!
// All operations automatically compress/decompress
await redis.AddAsync("large-data", myLargeObject); // stored compressed
var obj = await redis.GetAsync<MyObject>("large-data"); // decompressed automatically
Azure Managed Identity
var config = new RedisConfiguration { /* ... */ };
config.ConfigurationOptionsAsyncHandler = async opts =>
{
await opts.ConfigureForAzureWithTokenCredentialAsync(new DefaultAzureCredential());
return opts;
};
Connection Pooling
The pool automatically skips disconnected connections and falls back gracefully when all connections are down, letting StackExchange.Redis's internal reconnection logic recover.
| Strategy | Behavior |
|---|---|
LeastLoaded (default) |
Picks the connected connection with fewest outstanding commands |
RoundRobin |
Random selection among connected connections |
Serialization Behavior
All values stored in Redis go through the configured ISerializer. This means:
- A
stringvalue"hello"is stored as"\"hello\""(JSON-encoded) - Use
IRedisDatabase.Databasefor raw Redis operations without serialization - All serializers follow the same convention:
nullinput produces an empty byte array
Configuration Reference
| Property | Default | Description |
|---|---|---|
Hosts |
Required | Redis server endpoints |
Password |
null |
Redis password |
Database |
0 |
Database index |
Ssl |
false |
Enable TLS |
PoolSize |
5 |
Number of connections in the pool |
ConnectionSelectionStrategy |
LeastLoaded |
Pool selection strategy |
SyncTimeout |
5000 |
Sync operation timeout (ms) |
ConnectTimeout |
5000 |
Connection timeout (ms) |
KeyPrefix |
"" |
Prefix for all keys and channels |
AllowAdmin |
false |
Enable admin commands |
ClientName |
null |
Connection client name |
KeepAlive |
-1 |
Heartbeat interval (seconds). -1 = SE.Redis default, 0 = disabled |
ServiceName |
null |
Sentinel service name |
MaxValueLength |
0 |
Max serialized value size (0 = unlimited) |
WorkCount |
CPU*2 |
I/O threads per SocketManager |
ConnectRetry |
null |
Connection retry count |
CertificateValidation |
null |
TLS certificate validation callback |
CertificateSelection |
null |
TLS client certificate selection callback |
ConfigurationOptionsAsyncHandler |
null |
Async callback for custom ConfigurationOptions setup (e.g. Azure) |
Documentation
Full documentation is available in the doc/ folder:
Getting Started
Configuration
Serializers
Features
- Usage Guide — Add, Get, Replace, Bulk operations
- GeoSpatial Indexes
- VectorSet — AI/ML Similarity Search (Redis 8.0+)
- Redis Streams
- Pub/Sub Messaging
- Hash Field Expiry (Redis 7.4+)
- Compression — GZip, Brotli, LZ4, Snappy, Zstandard
Advanced
- Migration Guide: v11 → v12
- Logging & Diagnostics
- Multiple Redis Servers
- Azure Managed Identity
- OpenTelemetry
- Redis Information Middleware
- NuGet Packages
Contributing
Thanks to all the people who already contributed!
Please read CONTRIBUTING.md before submitting a pull request. PRs target the master branch only.
License
StackExchange.Redis.Extensions is Copyright © Ugo Lattanzi and other contributors under the MIT license.
Showing the top 20 packages that depend on StackExchange.Redis.Extensions.Core.
| Packages | Downloads |
|---|---|
|
StackExchange.Redis.Extensions.LegacyConfiguration
StackExchange.Redis.Extensions.LegacyConfiguration is a library that allows you to use App.Config or WebConfig with StackExchange.Redis.Extensions
|
10 |
|
StackExchange.Redis.Extensions.LegacyConfiguration
StackExchange.Redis.Extensions.LegacyConfiguration is a library that allows you to use App.Config or WebConfig with StackExchange.Redis.Extensions
|
8 |
|
StackExchange.Redis.Extensions.LegacyConfiguration
StackExchange.Redis.Extensions.LegacyConfiguration is a library that allows you to use App.Config or WebConfig with StackExchange.Redis.Extensions
|
7 |
.NET 10.0
- StackExchange.Redis (>= 2.12.14)
.NET 8.0
- StackExchange.Redis (>= 2.12.14)
.NET 9.0
- StackExchange.Redis (>= 2.12.14)
.NET Standard 2.1
- StackExchange.Redis (>= 2.12.14)
- System.Runtime.CompilerServices.Unsafe (>= 6.1.2)
| Version | Downloads | Last updated |
|---|---|---|
| 13.0.1 | 1 | 25.08.2026 |
| 13.0.0 | 1 | 25.08.2026 |
| 12.6.0 | 1 | 25.08.2026 |
| 12.5.0 | 2 | 09.07.2026 |
| 12.2.0 | 4 | 26.05.2026 |
| 12.1.0 | 4 | 28.04.2026 |
| 12.0.0 | 3 | 28.04.2026 |
| 11.0.0 | 9 | 20.02.2025 |
| 10.2.0 | 9 | 20.02.2025 |
| 10.1.0 | 9 | 20.02.2025 |
| 10.0.2 | 9 | 20.02.2025 |
| 10.0.1 | 8 | 20.02.2025 |
| 10.0.0 | 8 | 20.02.2025 |
| 9.1.0 | 8 | 03.06.2025 |
| 9.0.0 | 8 | 03.06.2025 |
| 8.0.5 | 8 | 03.06.2025 |
| 8.0.4 | 8 | 03.06.2025 |
| 8.0.3 | 8 | 03.06.2025 |
| 8.0.2 | 7 | 03.06.2025 |
| 8.0.1 | 7 | 03.06.2025 |
| 8.0.0 | 8 | 03.06.2025 |
| 7.2.1 | 6 | 03.06.2025 |
| 7.1.1 | 7 | 03.06.2025 |
| 7.0.1 | 8 | 03.06.2025 |
| 7.0.0 | 8 | 03.06.2025 |
| 7.0.0-pre | 10 | 20.02.2025 |
| 6.4.5 | 7 | 03.06.2025 |
| 6.4.3 | 7 | 03.06.2025 |
| 6.4.2 | 8 | 03.06.2025 |
| 6.4.1 | 7 | 03.06.2025 |
| 6.4.0 | 7 | 03.06.2025 |
| 6.3.6 | 7 | 03.06.2025 |
| 6.3.5 | 7 | 03.06.2025 |
| 6.3.4 | 7 | 03.06.2025 |
| 6.3.3 | 7 | 03.06.2025 |
| 6.3.2 | 7 | 03.06.2025 |
| 6.3.1 | 8 | 20.02.2025 |
| 6.3.0 | 8 | 03.06.2025 |
| 6.2.2 | 7 | 03.06.2025 |
| 6.2.1 | 8 | 03.06.2025 |
| 6.2.0 | 8 | 03.06.2025 |
| 6.1.7 | 8 | 03.06.2025 |
| 6.1.6 | 7 | 03.06.2025 |
| 6.1.5 | 8 | 03.06.2025 |
| 6.1.1 | 7 | 03.06.2025 |
| 6.1.0 | 8 | 03.06.2025 |
| 6.0.11 | 8 | 20.02.2025 |
| 6.0.10-pre | 9 | 20.02.2025 |
| 6.0.9-pre | 10 | 20.02.2025 |
| 6.0.8-pre | 9 | 20.02.2025 |
| 6.0.7-pre | 10 | 20.02.2025 |
| 6.0.6-pre | 10 | 20.02.2025 |
| 6.0.5-pre | 10 | 20.02.2025 |
| 6.0.4-pre | 9 | 20.02.2025 |
| 6.0.3-pre | 10 | 20.02.2025 |
| 6.0.2-pre | 10 | 20.02.2025 |
| 5.5.0 | 8 | 03.06.2025 |
| 5.4.0 | 11 | 10.02.2025 |
| 5.3.0 | 8 | 03.06.2025 |
| 5.2.0 | 8 | 03.06.2025 |
| 5.1.2 | 7 | 03.06.2025 |
| 5.1.1 | 7 | 03.06.2025 |
| 5.1.0 | 8 | 03.06.2025 |
| 5.0.3 | 8 | 03.06.2025 |
| 5.0.2 | 8 | 03.06.2025 |
| 5.0.1 | 9 | 03.06.2025 |
| 5.0.1-pre | 10 | 20.02.2025 |
| 5.0.0 | 8 | 03.06.2025 |
| 5.0.0-pre | 10 | 20.02.2025 |
| 4.0.5 | 9 | 03.06.2025 |
| 4.0.4 | 9 | 03.06.2025 |
| 4.0.3 | 8 | 03.06.2025 |
| 4.0.2 | 9 | 03.06.2025 |
| 4.0.1 | 8 | 03.06.2025 |
| 4.0.0 | 8 | 03.06.2025 |
| 3.5.0 | 9 | 03.06.2025 |
| 3.4.0 | 7 | 03.06.2025 |
| 3.3.0 | 7 | 03.06.2025 |
| 3.2.0 | 8 | 03.06.2025 |
| 3.1.0 | 9 | 03.06.2025 |
| 3.0.1 | 8 | 03.06.2025 |
| 3.0.0 | 8 | 03.06.2025 |
| 3.0.0-dev | 11 | 20.02.2025 |
| 2.4.0 | 12 | 23.05.2025 |
| 2.3.0 | 8 | 03.06.2025 |
| 2.2.0 | 8 | 03.06.2025 |
| 2.1.0 | 8 | 03.06.2025 |
| 2.0.0 | 8 | 03.06.2025 |
| 1.4.0 | 8 | 03.06.2025 |
| 1.3.6 | 7 | 03.06.2025 |
| 1.3.5 | 7 | 03.06.2025 |
| 1.3.3 | 7 | 03.06.2025 |
| 1.3.2 | 7 | 03.06.2025 |
| 1.3.1 | 7 | 03.06.2025 |
| 1.3.0 | 8 | 03.06.2025 |
| 1.2.0 | 8 | 03.06.2025 |
| 1.1.14 | 8 | 20.02.2025 |
| 1.1.13 | 8 | 20.02.2025 |
| 1.1.12 | 10 | 20.02.2025 |
| 1.1.11 | 9 | 20.02.2025 |
| 1.1.10 | 8 | 20.02.2025 |
| 1.1.9 | 9 | 03.06.2025 |
| 1.1.8 | 7 | 03.06.2025 |
| 1.1.7 | 7 | 03.06.2025 |
| 1.1.6 | 7 | 03.06.2025 |
| 1.1.5 | 6 | 03.06.2025 |
| 1.1.3 | 7 | 03.06.2025 |
| 1.1.2 | 7 | 03.06.2025 |
| 1.1.1 | 8 | 03.06.2025 |
| 1.1.0 | 7 | 03.06.2025 |
| 1.0.0 | 9 | 03.06.2025 |