skip to content
Stylized letter A in teal with pink sparkle accents Khalid Abuhakmeh

StackExchange.Redis Connection String Format (and redis:// URIs)

/ 5 min read

Updated:

A StackExchange.Redis connection string is a comma-separated list of endpoints followed by key=value options. Here’s a typical one:

my-redis.example.com:6380,password=s3cr3t,ssl=true,abortConnect=false

Pass it straight to ConnectionMultiplexer.Connect and you’re connected:

using StackExchange.Redis;
var redis = ConnectionMultiplexer.Connect(
"my-redis.example.com:6380,password=s3cr3t,ssl=true,abortConnect=false");
var db = redis.GetDatabase();
await db.StringSetAsync("hello", "world");

The rest of this post covers the format, the options you’ll reach for most often, and what to do with the redis:// URIs many hosting providers give you, since StackExchange.Redis won’t parse those.

Install StackExchange.Redis from NuGet

If you haven’t already, add the StackExchange.Redis NuGet package to your project.

Terminal window
dotnet add package StackExchange.Redis

The Connection String Format

The official configuration docs describe the rules, and they boil down to three:

  1. Tokens are separated by commas.
  2. A token without an = is a server endpoint, written as host or host:port.
  3. A token with an = is an option, such as password=s3cr3t.

If you leave off the port, StackExchange.Redis uses 6379, or 6380 when ssl=true.

Here are a few connection strings you’ll run into:

# Local Redis on the default port
localhost
# Local Redis with a password and a non-default database
localhost:6379,password=s3cr3t,defaultDatabase=2
# Redis 6+ with an ACL user
redis.example.com:6379,user=app,password=s3cr3t
# Azure Cache for Redis
contoso.redis.cache.windows.net:6380,password=<access-key>,ssl=true,abortConnect=false
# A primary/replica pair (the client figures out which is the primary)
redis0:6379,redis1:6379,password=s3cr3t

Common Connection String Options

StackExchange.Redis supports a lot of options. These are the ones I find myself using most. Each option maps to a ConfigurationOptions property with the same name in PascalCase, except abortConnect, which maps to AbortOnConnectFail, and name, which maps to ClientName.

Option Default What it does
password={string} null Password for the Redis server
user={string} null ACL username (Redis 6 and later)
ssl={bool} false Use TLS. Most cloud providers require this
abortConnect={bool} true (false on Azure) When true, Connect throws if no server is available
defaultDatabase={int} null Database index used by GetDatabase()
connectTimeout={int} 5000 Timeout in milliseconds for connecting
syncTimeout={int} 5000 Timeout in milliseconds for synchronous operations
asyncTimeout={int} same as syncTimeout Timeout in milliseconds for asynchronous operations
connectRetry={int} 3 Number of attempts during the initial connect
name={string} null Name shown for this connection in CLIENT LIST
allowAdmin={bool} false Enables risky commands like FLUSHDB and CONFIG

Set abortConnect=false in production. With the default of true, your app fails to start if Redis is unreachable for a moment. With false, the multiplexer keeps retrying in the background and recovers when Redis comes back.

Building the Configuration in Code

You don’t have to keep everything in a string. ConfigurationOptions.Parse turns a connection string into an object you can tweak before connecting. This is useful when the basics live in configuration and some values are only known at runtime.

var options = ConfigurationOptions.Parse(
builder.Configuration.GetConnectionString("Redis")!);
options.ClientName = "orders-api";
options.AbortOnConnectFail = false;
var redis = ConnectionMultiplexer.Connect(options);

It works the other way too. Calling options.ToString() gives you back the equivalent connection string, which helps when you’re debugging what a configuration turned into.

Register StackExchange.Redis in ASP.NET Core

ConnectionMultiplexer is expensive to create and designed to be shared, so register it as a singleton. IDatabase is a cheap pass-through object, so you can resolve it whenever you need it.

{
"ConnectionStrings": {
"Redis": "localhost:6379,abortConnect=false"
}
}
using StackExchange.Redis;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddSingleton<IConnectionMultiplexer>(_ =>
ConnectionMultiplexer.Connect(
builder.Configuration.GetConnectionString("Redis")!));
builder.Services.AddScoped(sp =>
sp.GetRequiredService<IConnectionMultiplexer>().GetDatabase());
var app = builder.Build();
app.MapGet("/visits", async (IDatabase db) =>
await db.StringIncrementAsync("visits"));
app.Run();

Converting a redis:// URI to a StackExchange.Redis Connection String

Many hosting providers, along with redis-cli -u, give you the connection details as a URI:

redis://username:password@host:port/database
rediss://username:password@host:port/database

The rediss:// scheme (with two s’s) means TLS. StackExchange.Redis doesn’t understand either scheme, so passing a URI straight to ConnectionMultiplexer.Connect won’t work. You have to convert it first.

System.Uri already knows how to pull a URI apart, so the conversion is short. The extension method below handles:

  • both redis:// and rediss://, setting Ssl for the latter
  • a username and password, a password only (redis://:password@host), or no credentials at all
  • percent-encoded characters in the password, like %40 for @
  • an optional database number in the path
  • a missing port, which defaults to 6379
using StackExchange.Redis;
public static class RedisUri
{
public static ConfigurationOptions Parse(string connectionUri)
{
var options = new ConfigurationOptions();
options.ApplyRedisUri(connectionUri);
return options;
}
public static ConfigurationOptions ApplyRedisUri(
this ConfigurationOptions options,
string connectionUri)
{
if (!Uri.TryCreate(connectionUri, UriKind.Absolute, out var uri) ||
uri.Scheme is not ("redis" or "rediss"))
{
throw new ArgumentException(
"Expected a URI like redis://user:password@host:port/db " +
"or rediss://... for TLS.",
nameof(connectionUri));
}
var port = uri.Port > 0 ? uri.Port : 6379;
options.EndPoints.Add(uri.Host, port);
options.Ssl = uri.Scheme == "rediss";
if (!string.IsNullOrEmpty(uri.UserInfo))
{
var parts = uri.UserInfo.Split(':', 2);
if (parts.Length == 2)
{
var user = Uri.UnescapeDataString(parts[0]);
if (user.Length > 0) options.User = user;
options.Password = Uri.UnescapeDataString(parts[1]);
}
else
{
// redis://password@host is treated as a password-only URI
options.Password = Uri.UnescapeDataString(parts[0]);
}
}
var path = uri.AbsolutePath.Trim('/');
if (int.TryParse(path, out var database))
{
options.DefaultDatabase = database;
}
return options;
}
}

Here’s what a few URIs turn into. The right-hand side is the output of ToString() on the resulting ConfigurationOptions:

redis://localhost
-> localhost:6379,ssl=False
redis://default:s3cr3t@redis.example.com:12345
-> redis.example.com:12345,user=default,password=s3cr3t,ssl=False
rediss://:p%40ss@redis.example.com:6380/2
-> redis.example.com:6380,password=p@ss,ssl=True,defaultDatabase=2

Since ApplyRedisUri is an extension method on ConfigurationOptions, you can still set anything the URI can’t express before you connect:

var options = RedisUri.Parse(builder.Configuration["REDIS_URL"]!);
options.AbortOnConnectFail = false;
options.ClientName = "orders-api";
builder.Services.AddSingleton<IConnectionMultiplexer>(
ConnectionMultiplexer.Connect(options));

Hopefully, you find this extension method helpful the next time a provider hands you a redis:// URI. For every option I didn’t cover here, see the StackExchange.Redis configuration docs.

Related Posts