Skip to content
Spice Framework on GitHub

Redis starter

frameworkMaturity: previewSource: spice@c0641b3Exact reviewed source

github.com/spice-framework/starter-redis is an independently versioned, opt-in integration built on the official go-redis client. Importing it or adding its dependency never activates it. Its explicit-constructor manifest contributes cache.redis and data.redis capabilities and pins the reviewed dependency version.

Client ownership and security

Open validates configuration and creates a pool without network I/O:

client, cleanup, err := redis.Open(redis.Options{
URL: "rediss://default:secret@cache.example.test:6380/0",
ClientName: "orders-service",
})

rediss with TLS 1.2 or newer and authenticated access are the defaults. Plaintext redis:// and missing credentials require the independent AllowInsecure and AllowUnauthenticated opt-ins intended for controlled local environments. URLs must identify one standalone server and database; query options, fragments, Unix sockets, and ambiguous hosts are rejected. Errors never contain the URL or credentials.

Spice fixes protocol, retry, timeout, FIFO pool, connection-limit, idle, and lifetime defaults. This avoids CPU-dependent pool sizing and unbounded connections. Each network operation uses its caller’s context. Open returns an exact lifecycle.Cleanup; generated applications can register it immediately for rollback and reverse shutdown. Ping is explicit, so construction never performs hidden network access.

Typed distributed cache

NewJSONStore[V] implements cache.Store[string,V]:

orders, err := redis.NewJSONStore[Order](
client,
redis.StoreOptions{
Definition: cache.Definition{
ID: "orders.by-id",
Module: "example.com/shop/orders",
},
Prefix: "orders-by-id",
MaxValueBytes: 1 << 20,
},
cacheObserver,
)

The prefix is required and prevents accidental cross-cache key collisions. Keys and prefixes are bounded printable identities. Get uses a bounded GETRANGE, so an oversized remote value is rejected without requesting its full payload. Put rejects negative TTLs, unsupported JSON values, and encoded values over the configured limit. Zero TTL means no expiration. Delete is idempotent.

Local snapshots count successful hits, misses, puts, and effective deletes. Redis owns distributed size, eviction, and expiration cardinality, so those snapshot fields remain zero. Observations contain only cache and module identity plus bounded operation metadata—never keys, values, URLs, or credentials.

Integration verification

The tagged integration test requires SPICE_REDIS_TEST_URL. It exercises a real server, expiration, typed encoding, cancellation, observations, and cleanup. The reviewed test image is redis:8.4.0-alpine@sha256:4eec4565e45aa0b3966554c866bc73211e281b0b3d89fe9a33c982e6faca809d.

go test -tags=integration -race -shuffle=on -count=1 ./...

Production credentials and endpoints belong in typed, redacted application configuration. They must never be annotation arguments or committed starter manifests.