Skip to main content
Swytch Documentation
Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Back to homepage

Swytch vs Redis (Enterprise)

Redis Enterprise and Swytch both offer multi-region active-active replication. That’s the shared ground. The question this page is about is what “active-active” actually means in each product, because the answer is not the same.

Redis Enterprise achieves active-active through CRDTs. CRDTs are a beautiful piece of theoretical work, and for the right data types they give you genuine convergence guarantees. But Redis’s implementation has specific consequences that matter if you’re running queues, streams, counters, or any destructive operation across regions. Lists can deliver the same element twice on concurrent pops. Streams can skip entries on reads, re-deliver acknowledged ones under traffic redirection, and produce out-of-order IDs across consecutive read commands. All of this is documented by Redis directly. The section below walks through the specifics.

Swytch’s active-active uses envelope-commit over a causal DAG. When two instances issue concurrent RPOP calls on the same list, the DAG serializes them so each consumes a distinct position. Both workers get an element; neither gets a duplicate; the list shrinks by two. Same commands, different outcome from Redis Enterprise: exactly-once delivery instead of at-least-once.

For cost comparisons, see Economics of Swytch.


The short version

Redis EnterpriseSwytch
DeploymentDedicated cluster, managed or self-hostedSidecar or standalone binary, one or many nodes
NodesPrimary-replica per region, synced via CRDTOne or more per region, active-active
WritersEvery region (via Active-Active / CRDB)Every node, concurrently
Network needed?Yes, between regions and clientsYes, between nodes; app-to-node is local
Wire protocolRESPv2 / RESPv3RESPv2 / RESPv3
Command setRedis commands + Enterprise modulesRedis commands, 100% compatible
ReplicationAsynchronous CRDT merge between regionsSynchronous to interested nodes
Concurrent list popsAt-least-once (per Redis’s list docs)Exactly-once via envelope-commit
Stream semanticsXREAD may skip entries; XREADGROUP at-least-once across regions (per Redis’s streams docs)Single-node Redis semantics across any number of regions
Partition handlingPer-region writes continue, CRDT merges on healBoth sides continue; non-transactional writes merge on heal
DurabilityDisk (RDB + AOF), replicationIn-memory across subscribed nodes by default; disk via Swytch Cloud
ModulesRediSearch, RedisJSON, RedisGraph, RedisTimeSeries, etc.Not supported
Operational surfaceManaged service or dedicated ops teamOne binary, DNS-based membership
LicenseCommercial, per-regionAGPL (open source) + commercial

Active-active, honestly

The question every multi-region deployment has to answer is what happens when two regions write to the same thing at the same time.

Redis Enterprise’s answer is CRDTs. For commutative operations (counters, sets), CRDTs work well; the merge is mathematically guaranteed to produce the same result on every region. For non-commutative operations, Redis has designed specific CRDT behaviors per data type, and for some of those data types, the behavior has correctness implications.

The most significant is lists. Redis Enterprise’s Active-Active lists documentation states, verbatim: “Lists in Active-Active databases guarantee that each element is POP-ed at least once, but cannot guarantee that each element is POP-ed only once.” The documentation goes on to explain: “Two parallel RPOP operations performed by two different Active-Active database instances can get the same element in the case of a concurrent operation.”

The recommended mitigation, per Redis: route all pops to a single Active-Active instance.

That recommendation is the mitigation, but it also erases the reason you bought Active-Active. If every destructive operation has to funnel through one instance, you have one instance of availability for that workload, in one region, with the other regions’ Active-Active nodes along for the ride. It’s a workaround, not a solution.

Streams are worse, because streams are specifically the primitive Redis users reach for when they need reliable event processing. The Active-Active streams documentation names several failure modes:

  • XREAD may skip entries when a stream is written from more than one region. Redis’s recommendation: “For reliable stream iteration, use XREADGROUP instead.”
  • XREADGROUP across regions “can result in regions reading the same entries”, because “Active-Active Streams is designed for at-least-once reads or a single consumer.”
  • Under traffic redirection to a different region, XREADGROUP can return entries that have already been read and even entries that have already been acknowledged.
  • Sequential XREADGROUP calls can reply with decreasing IDs, because ordering isn’t guaranteed across commands.
  • Unless you restrict XADD to strict ID generation mode (which rejects full IDs with both a millisecond and sequence part), duplicate stream entry IDs are possible.

None of these are obscure edge cases. They’re the published behavior of the primitive a lot of Redis users specifically chose because they needed reliability. “Designed for at-least-once reads” is a quoted claim from Redis’s own documentation, not a framing Swytch is putting on it.

The same issue shapes other patterns. Concurrent transactions (MULTI/EXEC across Active-Active instances) rely on the same CRDT machinery and have the same fundamental constraint: the merge function determines the outcome, and for some merge functions the outcome isn’t what a serializable semantics would give you.

Swytch’s active-active is serializable. Concurrent operations get ordered before they commit, and the outcome of any set of operations is consistent with some serial execution of them; not a merge of concurrent ones.

The consequence, for streams specifically: using Swytch in a single region or across fifty is semantically equivalent to using single-node Redis. XREAD doesn’t skip entries. XREADGROUP doesn’t re-deliver acknowledged ones. Consecutive reads return IDs in the expected order. None of this requires stream-specific implementation cleverness; it falls out of the fact that the whole database is serializable. What changes as you add regions is speed, bounded by physics; a write committed in Sydney has to reach a subscriber in Frankfurt before Frankfurt sees it, and that takes the cross-region RTT. The semantics don’t change. The latency does.

This is not a marginal improvement. For any stateful workload (queues, counters, leaderboards, rate limiters, inventory, anything where duplicate processing has a cost) it’s the difference between “works correctly” and “works until it doesn’t, and when it doesn’t you find out in an incident.”


Where each one fits

Reach for Redis Enterprise when:

  • You need Redis modules (RediSearch, RedisJSON, RedisGraph, etc.) that aren’t in OSS.
  • Your workload is primarily key-value caching where CRDTs are well-behaved (non-destructive operations, commutative updates).
  • You’ve already invested in Redis Enterprise tooling and the team knows the operational model.

Reach for Swytch when:

  • You’re running queues, counters, or any destructive operation across regions and need exactly-once semantics.
  • You want real transactional isolation in multi-region deployments, not CRDT merge semantics.
  • You want simpler ops. No separate cluster tier, no per-region license, just add servers.
  • You want to cut infrastructure and licensing costs. See Economics of Swytch for the math.

The one-paragraph summary

Redis Enterprise and Swytch both solve multi-region active-active, and they solve it differently. Redis Enterprise uses CRDTs, which for the right data types work beautifully but for destructive operations like list pops can deliver the same element to two different regions concurrently (a limitation Redis’s own documentation is explicit about). The recommended workaround (route pops through one instance) is not Active-Active in any meaningful sense. Swytch uses envelope-commit over a causal DAG, which gives you exactly-once semantics across regions for destructive operations, transactions, and anything else where correctness under concurrency matters. If your workload fits in the CRDT sweet spot and you’re already invested in Enterprise tooling, Enterprise is a reasonable choice. If your workload includes the kinds of operations CRDTs don’t handle cleanly, and most real application workloads do, Swytch is what active-active looks like when it’s built for correctness first.