Table of contents
Part of nurago, a collection of independent Go packages for backend services.
import "github.com/tecnickcom/nurago/pkg/valkey"
Key/value storage, typed payloads and Pub/Sub over valkey-go, the client for Valkey.
c, err := valkey.New(ctx, &valkey.SrvOptions{InitAddress: []string{"localhost:6379"}})
defer c.Close()
Why a separate package from redis
Valkey is the Linux Foundation fork of Redis, created after Redis moved off its BSD licence in 2024. It remains protocol-compatible, so most operations behave identically.
The clients are not the same library, though. valkey-go is a different implementation with a different option type and a different command-building model, built around client-side caching and pipelining. Wrapping both behind one type would mean either exposing the lowest common denominator or leaking whichever client was underneath.
Two packages keep each one’s options honest: SrvOptions aliases valkey-go’s ClientOption here, and go-redis’s Options in redis. Configuration is documented by the underlying library in both cases, with no translation layer to learn.
It also keeps the dependency split. A service using one does not compile the other; see /docs/dependency-footprint/.
The application-facing API is deliberately parallel, so moving between them is a change of import and constructor rather than a rewrite.
Pinned Pub/Sub subscription
When channels are declared with WithChannels, a pre-built, pinned subscription command starts a background subscription feeding Receive and ReceiveData one message per call.
The pinning follows from how valkey-go works: that client multiplexes commands over a shared connection by default, and a subscription cannot share one, because a subscribed connection is in a mode where ordinary commands are not accepted. The subscription therefore gets a dedicated connection.
The same lifetime rule as redis applies, and the same trap: the subscription runs until Close is called. Cancelling the context passed to New does not stop it. Close belongs in the shutdown path, not in a defer on a startup function.
Address validation and injection
New validates the server address before dialling, skipped when a client is injected through WithValkeyClient. A malformed address fails at startup rather than on the first request.
WithValkeyClient is the test seam.
Typed payloads
SetData and GetData serialise around the raw operations, with DefaultMessageEncodeFunc and DefaultMessageDecodeFunc replaceable at construction. Choose an interoperable encoding where anything other than this service reads the data.
One message per call
Receive returns a single message per invocation rather than a channel, keeping back-pressure at the call site so a slow consumer cannot accumulate an unbounded backlog.
As with Redis, Pub/Sub is fire-and-forget: no acknowledgement, no replay, nothing delivered to a subscriber that was not connected. Durable messaging is kafka or sqs.
Dependencies
Reaches github.com/valkey-io/valkey-go.
Links
- Reference documentation
- Source code
- The Redis equivalent: redis
- Durable messaging: kafka, sqs
- All nurago packages