Coming From Redis: Pointing Your .NET App at Zaris
If your .NET services already talk to Redis, moving to Zaris doesn't have to be a rewrite. Zaris is a distributed, in-memory, replicated key/value store built natively for .NET — and as of 2.0.0 it speaks two protocols at once: its own efficient binary protocol for first-class .NET clients, and a Redis-compatible RESP2 front-end that any Redis client in any language can point at.
That gives you two honest migration paths, and they're not mutually exclusive. You can start with the zero-change RESP path to get Zaris under load today, then adopt the native client where it pays off. This post walks both, and gives you a clear rule for picking.
Path A — keep your Redis client
The fastest way to try Zaris is to not change your code at all. Enable the RESP listener on your Zaris nodes and point your existing Redis client at a node's RESP port. Zaris accepts ordinary Redis commands, routes each one to the partition that owns the key, and replies over the wire your client already understands.
Here's StackExchange.Redis talking to Redis:
var mux = await ConnectionMultiplexer.ConnectAsync("redis-0:6379");
var db = mux.GetDatabase();
await db.StringSetAsync("session:42", payload, TimeSpan.FromMinutes(30));
var back = await db.StringGetAsync("session:42");
And here's the same code against Zaris — the only thing that changes is the host:
var mux = await ConnectionMultiplexer.ConnectAsync("zaris-0:6379");
var db = mux.GetDatabase();
await db.StringSetAsync("session:42", payload, TimeSpan.FromMinutes(30));
var back = await db.StringGetAsync("session:42");
No new package, no API changes. Under the hood, Zaris hashes keys with the same CRC16(key) % 16384 slot math Redis Cluster uses, so a cluster-aware client routes each key directly to the node that owns it — no proxy, no extra hop, just like Redis Cluster. (Behind a plain load balancer or Sentinel, any node will accept any key instead.) If you want the details of how that works and how failover behaves, see how Zaris speaks the Redis protocol and the Redis protocol reference.
What to watch on this path:
- RESP2 only. The front-end speaks RESP2, so pin your Redis client to versions that negotiate RESP2 and don't assume RESP3 push frames.
- Some commands are cleanly rejected, not faked. Lua/
EVAL, geo, HyperLogLog, bitmaps, and RDB/AOF persistence aren't implemented — Zaris returns a clear "unsupported" rather than pretending. The full breakdown of what works is in the Redis command compatibility matrix, measured againstStackExchange.Redis 2.8.16: roughly 126 commands supported, 92 cleanly unsupported, zero surprises. - The coordination commands you actually use are there.
MULTI/EXECmap onto Zaris's native two-phase-commit transactions,SET key val NX PXgives you the distributed-lock pattern, and keyspace notifications work.
This path is ideal when a service is polyglot, when Redis is shared across teams, or when you just want Zaris running in staging by this afternoon.
Path B — the native .NET client
Once Zaris is proving itself, the native client is where .NET-first apps get the most out of it. It isn't a protocol wrapper — it's a real .NET client with typed APIs, and its hot-path operations (Get/Put/Delete/Expire/Persist/TTL) return ValueTask, so they allocate nothing when they complete synchronously.
Adoption is mostly configuration. If you're on ASP.NET Core and using Redis as your IDistributedCache, the switch is two lines:
// Program.cs
builder.Services.AddClustronZaris("cache", "zaris://cache-0:7861,cache-1:7861/app");
builder.Services.AddClustronDistributedCache("cache");
// ...then inject IDistributedCache (or HybridCache) and use it exactly as before.
Connection strings are the same everywhere — in-process, remote, Docker, or Kubernetes:
zaris://host:7861/store
Use zariss:// for TLS, comma-separate seed hosts for failover, and supply tokens safely with env: or file: rather than inline.
Beyond caching, the native client gives you things the Redis API simply doesn't model as first-class operations: typed hashes, lists, sets, sorted sets, and Streams; compare-and-swap; bulk and batch operations; scan and prefix queries; and a full set of coordination primitives — transactions, distributed locks, leader election, leases, counters, rate limiting, and a job queue. If you've been assembling those out of Redis building blocks and Lua, they're native here.
When to pick which
A simple rule:
- Reach for Path A (RESP) when the caller isn't .NET, when Redis is shared across services, or when you want the fastest possible trial with zero code change.
- Reach for Path B (native) when the service is .NET, when you care about allocation-free throughput, or when you want typed data structures and coordination primitives instead of hand-rolled patterns.
Most teams land on a mix — RESP for the polyglot edges, native for the .NET core — and that's a perfectly good end state, not a half-migration.
One upgrade note
Zaris 2.0.0 is a major release with a wire-protocol break on the native client: cluster routing moved to CRC16-aligned hashing, and the protocol minimum is now 2. A 2.0.0 server rejects pre-2.0 clients at HELLO, so upgrade your native clients and servers together. The RESP front-end is unaffected — Redis clients don't participate in the native protocol at all. The full story is in the 2.0.0 announcement.
Getting started
dotnet add package Clustron.Zaris.SDK --version 2.0.0
- Try Redis-compatibility hands-on: Coming from Redis in the docs
- See the full command matrix: Redis command compatibility
- Weigh it up: Clustron vs Redis
- Install anywhere: clustron.io/install
If your stack is .NET and you've been running Redis mostly because it was the obvious choice, Zaris lets you keep everything that works today and pick up native integration on your own schedule.