{
  "schema_version": 2,
  "id": "develop/clients/dotnet/connect",
  "title": "Connect to the server",
  "url": "https://redis.io/docs/latest/develop/clients/dotnet/connect/",
  "summary": "Connect your .NET application to a Redis database",
  "aliases": [
    "/develop/connect/clients/dotnet/connect/"
  ],
  "tags": [
    "docs",
    "develop",
    "stack",
    "oss",
    "rs",
    "rc",
    "oss",
    "kubernetes",
    "clients"
  ],
  "last_updated": "2026-10-13T14:53:04+01:00",
  "page_type": "content",
  "content_hash": "0129262f34172bee17a1215614ca6b13bbe905fe4e4c6a0940151ff29a3e9378",
  "sections": [
    {
      "id": "basic-connection",
      "title": "Basic connection",
      "role": "overview",
      "text": "You can connect to the server simply by passing a string of the\nform \"hostname:port\" to the `Connect()` method (for example,\n\"localhost:6379\"). However, you can also connect using a\n`ConfigurationOptions` parameter. Use this to specify a\nusername, password, and many other options:\n\n[code example]\n\n> [!NOTE]\n> Unlike other clients, StackExchange.Redis doesn't support\n> [Connection URLs](https://redis.io/docs/latest/develop/clients/connection-urls#stackexchangeredis-and-nredisstack-net)\n> but it does support its own similar configuration string format.\n> See [Connection URLs](https://redis.io/docs/latest/develop/clients/connection-urls#stackexchangeredis-and-nredisstack-net)\n> to learn how to convert a standard URL to a configuration string."
    },
    {
      "id": "connect-to-a-redis-cluster",
      "title": "Connect to a Redis cluster",
      "role": "content",
      "text": "The basic connection will use the\n[Cluster API](https://redis.io/docs/latest/operate/rs/clusters/optimize/oss-cluster-api)\nif it is available without any special configuration. However, if you know\nthe addresses and ports of several cluster nodes, you can specify them all\nduring connection in the `Endpoints` parameter:\n\n[code example]"
    },
    {
      "id": "connect-to-redis-sentinel",
      "title": "Connect to Redis Sentinel",
      "role": "content",
      "text": "To connect through [Redis Sentinel](https://redis.io/docs/latest/operate/oss_and_stack/management/sentinel),\nlist the Sentinels in `EndPoints` and set `ServiceName` to the name of the primary that\nthe Sentinels monitor. The client asks the Sentinels for the current primary.\n\n[code example]\n\nYou can also use a configuration string, such as\n`\"localhost:26379,localhost:26380,localhost:26381,serviceName=mymaster\"`.\n\nIf the Sentinels and the data nodes have different credentials, connect to the Sentinels\nfirst with `SentinelConnect()`, using the Sentinel credentials. Then call\n`GetSentinelMasterConnection()` with the credentials for the primary and replicas:\n\n[code example]\n\nThe connection also includes the replicas that the Sentinels report. To read from a\nreplica, pass `CommandFlags.PreferReplica` (or `CommandFlags.DemandReplica`) to a read-only\ncommand. Replication is asynchronous, so a replica can return stale data.\n\n[code example]"
    },
    {
      "id": "connect-to-your-production-redis-with-tls",
      "title": "Connect to your production Redis with TLS",
      "role": "content",
      "text": "When you deploy your application, use TLS and follow the [Redis security](https://redis.io/docs/latest/operate/oss_and_stack/management/security) guidelines.\n\nBefore connecting your application to the TLS-enabled Redis server, ensure that your certificates and private keys are in the correct format.\n\nTo convert user certificate and private key from the PEM format to `pfx`, use this command:\n\n[code example]\n\nEnter password to protect your `pfx` file.\n\nEstablish a secure connection with your Redis database using this snippet.\n\n[code example]"
    },
    {
      "id": "sni-hostname-selection-for-cluster-connections",
      "title": "SNI hostname selection for cluster connections",
      "role": "content",
      "text": "> [!NOTE]\n> The SNI precedence scheme described in this section\n> requires `StackExchange.Redis` v3.3.1 or later.\n\nWhen you connect with TLS to a cluster that `StackExchange.Redis` discovers through\n`CLUSTER SLOTS`, each discovered node needs its own\n[SNI hostname](https://en.wikipedia.org/wiki/Server_Name_Indication). This allows a shared load\nbalancer or proxy to route the TLS handshake to the right backend. `StackExchange.Redis`\nresolves the SNI hostname for a connection in this order:\n\n1. An explicitly configured `ConfigurationOptions.SslHost` always wins.\n2. Otherwise, a `DnsEndPoint` uses its own host.\n3. Otherwise, the client falls back to the default SNI provider.\n4. If none of these is available, the client uses the endpoint address.\n\nBecause of this order, `ConfigurationOptions.SslHost` only reports a value if you set one\nexplicitly; it doesn't report a host that the client inferred for you."
    },
    {
      "id": "connect-using-smart-client-handoffs-sch",
      "title": "Connect using Smart client handoffs (SCH)",
      "role": "content",
      "text": "*Smart client handoffs (SCH)* is a feature of Redis Cloud and\nRedis Software servers that lets them actively notify clients\nabout planned server maintenance shortly before it happens. This\nlets a client take action to avoid disruptions in service.\nSee [Smart client handoffs](https://redis.io/docs/latest/develop/clients/sch)\nfor more information about SCH.\n\n> [!NOTE]\n> SCH support in `StackExchange.Redis` requires v3.3.0 or later. In v3.3.0 and\n> v3.3.1, the SCH API is marked `[Experimental]`, and SCH is never enabled\n> unless you set `MaintenanceNotifications` yourself. From v3.4.0, the API is no\n> longer experimental, so the compiler no longer reports the `SER010`\n> diagnostic and you can remove any suppression you added for it.\n\nThe client enables SCH automatically, in `Auto` mode, when either of the\nfollowing is true:\n\n- You connect using a hostname that the client recognizes as Redis Cloud\n  (`*.cloud.redislabs.com`, `*.cloud.redis.io`, or `*.redislabs.com`) or\n  Azure Managed Redis (`*.redis.azure.net` or `*.redisenterprise.cache.azure.net`).\n- You name a provider profile with the `defaults` configuration key\n  (`defaults=enterprise`, `defaults=rediscloud`, or `defaults=amr`).\n\nFor any other endpoint, SCH is disabled by default. This includes Redis\nSoftware databases, which have no hostname pattern to recognize, and hosted\ndatabases that you reach through a CNAME, private DNS, or a proxy. For these,\neither set `defaults=enterprise`, which also applies that profile's other\ndefault settings, or enable SCH with the `MaintenanceNotifications`\nconfiguration option, in code or using the `maintNotifications` key in a\nconfiguration string:\n\n[code example]\n\nThe `ConfigurationOptions` object accepts the following SCH-related parameters:\n\n| Name | Description |\n| :-- | :-- |\n| `MaintenanceNotifications` | Whether to request SCH. The options are `Disabled` (the default, unless the client recognizes the endpoint or you set `defaults`), `Enabled` (require SCH and reject the connection, including a fallback to RESP2, if the server can't deliver it), and `Auto` (request SCH and tolerate a server that doesn't support it). |\n| `MaintenanceMovingEndpointType` | The endpoint type to request for a replacement node during a handoff. The options are `ServerDefault` (no preference), `Auto` (the default; derived from the connection's scheme and encryption), `InternalIp`, `InternalFqdn`, `ExternalIp`, `ExternalFqdn`, and `None`. |\n| `MaintenanceRelaxedTimeout` | The timeout to use for commands and connections while the server has announced maintenance. The default is 10 seconds. |\n| `MaintenanceRelaxedWindowMax` | The maximum time to keep using the relaxed timeout if no notification arrives to close the window. The default is three times `MaintenanceRelaxedTimeout`. |\n| `MaintenancePostEventRelaxedDuration` | How long to keep using the relaxed timeout after a closing notification, to cover trailing effects of the maintenance. |\n\nSubscribe to the `ConnectionMultiplexer.ServerMaintenanceEvent` event to\nobserve SCH notifications. This is the same event that some servers (such as\nAzure Cache for Redis) already use for their own maintenance notifications\n(see [Production usage](https://redis.io/docs/latest/develop/clients/dotnet/produsage#server-notification-events)),\nso check the runtime type of the event arguments to tell the two apart:\n\n[code example]\n\n`RedisConnectionException` and `RedisTimeoutException` both expose a\n`MaintenanceType` property, so you can tell whether a failure happened\nbecause of ongoing maintenance."
    },
    {
      "id": "multiplexing",
      "title": "Multiplexing",
      "role": "content",
      "text": "Although example code typically works with a single connection,\nreal-world code often uses multiple connections at the same time.\nOpening and closing connections repeatedly is inefficient, so it is best\nto manage open connections carefully to avoid this.\n\nSeveral other\nRedis client libraries use *connection pools* to reuse a set of open\nconnections efficiently. StackExchange.Redis uses a different approach called\n*multiplexing*, which sends all client commands and responses over a\nsingle connection. StackExchange.Redis manages multiplexing for you automatically.\nThis gives high performance without requiring any extra coding.\nSee\n[Connection pools and multiplexing](https://redis.io/docs/latest/develop/clients/pools-and-muxing)\nfor more information."
    }
  ],
  "examples": [
    {
      "id": "basic-connection-ex0",
      "language": "csharp",
      "code": "using StackExchange.Redis;\n\nConfigurationOptions conf = new ConfigurationOptions {\n    EndPoints = { \"localhost:6379\" },\n    User = \"yourUsername\",\n    Password = \"yourPassword\"\n};\n\nConnectionMultiplexer redis = ConnectionMultiplexer.Connect(conf);\nIDatabase db = redis.GetDatabase();\n\ndb.StringSet(\"foo\", \"bar\");\nConsole.WriteLine(db.StringGet(\"foo\")); // prints bar",
      "section_id": "basic-connection"
    },
    {
      "id": "connect-to-a-redis-cluster-ex0",
      "language": "csharp",
      "code": "ConfigurationOptions options = new ConfigurationOptions\n{\n    //list of available nodes of the cluster along with the endpoint port.\n    EndPoints = {\n        { \"localhost\", 16379 },\n        { \"localhost\", 16380 },\n        // ...\n    },            \n};\n\nConnectionMultiplexer cluster = ConnectionMultiplexer.Connect(options);\nIDatabase db = cluster.GetDatabase();\n\ndb.StringSet(\"foo\", \"bar\");\nConsole.WriteLine(db.StringGet(\"foo\")); // prints bar",
      "section_id": "connect-to-a-redis-cluster"
    },
    {
      "id": "connect-to-redis-sentinel-ex0",
      "language": "csharp",
      "code": "using StackExchange.Redis;\n\nConfigurationOptions conf = new ConfigurationOptions {\n    EndPoints = { \"localhost:26379\", \"localhost:26380\", \"localhost:26381\" },\n    ServiceName = \"mymaster\"\n};\n\nConnectionMultiplexer redis = ConnectionMultiplexer.Connect(conf);\nIDatabase db = redis.GetDatabase();\n\ndb.StringSet(\"foo\", \"bar\");\nConsole.WriteLine(db.StringGet(\"foo\")); // prints bar",
      "section_id": "connect-to-redis-sentinel"
    },
    {
      "id": "connect-to-redis-sentinel-ex1",
      "language": "csharp",
      "code": "using StackExchange.Redis;\n\n// Connect to the Sentinels with the Sentinel credentials.\nConfigurationOptions sentinelConf = new ConfigurationOptions {\n    EndPoints = { \"localhost:26379\", \"localhost:26380\", \"localhost:26381\" },\n    User = \"yourSentinelUsername\",\n    Password = \"yourSentinelPassword\"\n};\nConnectionMultiplexer sentinel = ConnectionMultiplexer.SentinelConnect(sentinelConf);\n\n// Connect to the primary with the Redis credentials.\nConfigurationOptions conf = new ConfigurationOptions {\n    ServiceName = \"mymaster\",\n    User = \"yourUsername\",\n    Password = \"yourPassword\"\n};\nConnectionMultiplexer redis = sentinel.GetSentinelMasterConnection(conf);\nIDatabase db = redis.GetDatabase();",
      "section_id": "connect-to-redis-sentinel"
    },
    {
      "id": "connect-to-redis-sentinel-ex2",
      "language": "csharp",
      "code": "// Read from a replica if one is available, otherwise from the primary.\nConsole.WriteLine(db.StringGet(\"foo\", CommandFlags.PreferReplica)); // prints bar",
      "section_id": "connect-to-redis-sentinel"
    },
    {
      "id": "connect-to-your-production-redis-with-tls-ex0",
      "language": "bash",
      "code": "openssl pkcs12 -inkey redis_user_private.key -in redis_user.crt -export -out redis.pfx",
      "section_id": "connect-to-your-production-redis-with-tls"
    },
    {
      "id": "connect-to-your-production-redis-with-tls-ex1",
      "language": "csharp",
      "code": "ConfigurationOptions options = new ConfigurationOptions\n{\n    EndPoints = { { \"my-redis.cloud.redislabs.com\", 6379 } },\n    User = \"default\",  // use your Redis user. More info https://redis.io/docs/latest/operate/oss_and_stack/management/security/acl/\n    Password = \"secret\", // use your Redis password\n    Ssl = true,\n    SslProtocols = System.Security.Authentication.SslProtocols.Tls12                \n};\n\noptions.CertificateSelection += delegate\n{\n    return X509CertificateLoader.LoadPkcs12FromFile(\"redis.pfx\", \"secret\"); // use the password you specified for pfx file\n};\noptions.CertificateValidation += ValidateServerCertificate;\n\nbool ValidateServerCertificate(\n        object sender,\n        X509Certificate? certificate,\n        X509Chain? chain,\n        SslPolicyErrors sslPolicyErrors)\n{\n    if (certificate == null) {\n        return false;       \n    }\n\n    var ca = X509CertificateLoader.LoadCertificateFromFile(\"redis_ca.pem\");\n    bool verdict = (certificate.Issuer == ca.Subject);\n    if (verdict) {\n        return true;\n    }\n    Console.WriteLine(\"Certificate error: {0}\", sslPolicyErrors);\n    return false;\n}\n\nConnectionMultiplexer muxer = ConnectionMultiplexer.Connect(options);   \n            \n//Creation of the connection to the DB\nIDatabase conn = muxer.GetDatabase();\n\n//send SET command\nconn.StringSet(\"foo\", \"bar\");\n\n//send GET command and print the value\nConsole.WriteLine(conn.StringGet(\"foo\"));",
      "section_id": "connect-to-your-production-redis-with-tls"
    },
    {
      "id": "connect-using-smart-client-handoffs-sch-ex0",
      "language": "csharp",
      "code": "var options = ConfigurationOptions.Parse(\"host:6379,maintNotifications=Auto,maintRelaxedTimeout=15\");\n\n// or, in code:\nvar options = new ConfigurationOptions {\n    EndPoints = { \"host:6379\" },\n    MaintenanceNotifications = MaintenanceNotificationMode.Auto,\n    MaintenanceRelaxedTimeout = TimeSpan.FromSeconds(15),\n};\n\nvar muxer = await ConnectionMultiplexer.ConnectAsync(options);",
      "section_id": "connect-using-smart-client-handoffs-sch"
    },
    {
      "id": "connect-using-smart-client-handoffs-sch-ex1",
      "language": "csharp",
      "code": "muxer.ServerMaintenanceEvent += (object sender, ServerMaintenanceEvent e) => {\n    if (e is PushMaintenanceEvent pme) {\n        // A server-native SCH notification.\n        Console.WriteLine($\"SCH notification: {pme.NotificationType} at {pme.EndPoint}\");\n    } else {\n        // An older, provider-specific notification (for example, from Azure Cache for Redis).\n        Console.WriteLine($\"Maintenance event: {e.RawMessage}\");\n    }\n};",
      "section_id": "connect-using-smart-client-handoffs-sch"
    }
  ]
}
