Skip to content

Choosing a backend

Gerasimos (Makis) Maropoulos edited this page May 28, 2026 · 1 revision

When to use this page

  • You're picking between Redis and NATS for Scale out.
  • You already use one of them and want to confirm it'll work.
  • You want a starting point for your own benchmark.

TL;DR

Use Redis unless you have a specific reason not to.

If you already run Redis for caching or sessions, the operational delta is near zero. NATS is the better choice if you want a smaller dependency, are already running it for service-to-service messaging, or want simpler clustering.

Either backend will saturate a single neffos instance long before it becomes the bottleneck for most chat / notification / live-update workloads.

Decision matrix

Question Redis NATS
Already in our stack? Often yes. Less common.
Operational overhead Familiar to most ops teams; single binary; rich tooling. Tiny binary (<20MB), simpler config, but less institutional muscle memory.
Memory footprint at idle ~few MB. Grows with key space. neffos uses none. ~few MB. neffos uses none.
CPU at high pub/sub rate Single-threaded pub/sub dispatcher; can become CPU-bound on large fan-outs. Multi-threaded; tends to scale better with cores.
Clustering cluster mode (sharded keys); neffos uses Clusters []string config. Gossip-based; just point each neffos instance at any node.
Auth requirepass, ACLs, TLS. NKey, JWT, mTLS.
Persistence RDB/AOF; neffos does not use it. JetStream; neffos does not use it.
Cross-DC Run a separate Redis per DC; bridge with a custom relay. Built-in cluster gossip across DCs.
Local dev story docker run --rm -p 6379:6379 redis. docker run --rm -p 4222:4222 nats.

What neffos actually needs from the broker

Both backends use only the pub/sub primitive, not the persistence or queue features:

  • Subscribe to a per-connection channel (for To:-targeted messages).
  • Subscribe to a per-namespace channel.
  • Publish a serialized neffos Message to the right channel.
  • Subscribe to a per-Ask channel for replies.

That means JetStream / RDB / cluster persistence are unused. Don't over-provision storage; do provision CPU and network for pub/sub fan-out.

Quick start

Redis

import "github.com/kataras/neffos/stackexchange/redis"

exc, err := redis.NewStackExchange(redis.Config{
    Network:     "tcp",
    Addr:        "127.0.0.1:6379",
    Password:    "",        // or os.Getenv("REDIS_PASSWORD")
    DialTimeout: 5 * time.Second,
    MaxActive:   10,        // pool size
}, "my-app")               // channel prefix, unique per neffos app
if err != nil { log.Fatal(err) }

server.UseStackExchange(exc)

Cluster mode:

exc, err := redis.NewStackExchange(redis.Config{
    Clusters: []string{"r1:6379", "r2:6379", "r3:6379"},
}, "my-app")

Pick a unique channel prefix per neffos app. If two unrelated apps share one Redis with the same prefix, they'll receive each other's broadcasts.

NATS

import "github.com/kataras/neffos/stackexchange/nats"
import nats "github.com/nats-io/nats.go"

exc, err := nats.NewStackExchange("nats://localhost:4222")
if err != nil { log.Fatal(err) }

server.UseStackExchange(exc)

With auth:

exc, err := nats.NewStackExchange("",
    nats.UserInfo("user", "pass"),
    // or nats.UserCredentials("/path/to/user.creds")
    // or nats.Secure(tlsConfig)
)

Set a unique subject prefix per neffos app:

exc.SubjectPrefix = "my-app.neffos"

Failure-mode comparison

What happens during a broker outage?

Scenario Redis NATS
Broker down at startup NewStackExchange returns error. Same.
Broker dies after startup radix PersistentPubSub keeps trying to reconnect; messages published during the outage are lost. NATS client reconnects automatically; messages published during the outage are lost.
Slow broker Publishes block briefly; can backpressure callers. Same.
Network partition Each instance still serves its local clients; cross-instance traffic is lost during the partition. Same.

Neither backend persists in-flight broadcasts in the default configuration. If you need durable broadcast (e.g. "every connected user must eventually see this notification"), persist it in your own store first and re-broadcast on reconnect.

Benchmark guidance

Numbers vary wildly with message size and fan-out, but a few rules of thumb:

  • A single Redis instance can push ~100K small pub/sub messages per second on commodity hardware.
  • A single NATS server can push ~5–10x that for the same workload.
  • The neffos in-process broadcaster (no StackExchange) is faster than either — scale-out is a network round-trip you pay for cross-instance delivery.

If you're approaching broker throughput limits, first check whether you can shard by namespace (each namespace is a separate channel/subject) before changing brokers.

See also

Clone this wiki locally