Redis: Distributed Caching & Beyond
Optimize your microservice performance with blitz-fast distributed caching using Redis.
Cache Architecture
GO-DUCK implements a "Cache-Aside" strategy. This ensures that your application remains resilient: if Redis is unreachable, a nil-check fallback in the cache layer skips straight to the database rather than erroring — plus a one-time connectivity probe at boot so a dead cache never blocks startup.
Multi-Tenant & Microservice Isolation
Standard caching in a multi-tenant app is dangerous. GO-DUCK solves this by Role-Prefixing every key automatically, using the caller's resolved tenant role (not a raw tenant ID). Your cache keys look like warehouse-service:public:User:123, preventing data leaks across tenants.
To prevent key collisions when multiple independent microservices share the same Redis/Valkey instance, GO-DUCK supports transparent namespacing using the key-prefix property in application.yml:
go-duck:
cache:
redis:
enabled: true
host: "localhost:6379"
key-prefix: "warehouse-service" # Custom namespace prefix
If key-prefix is left empty, the application automatically falls back to using the microservice name (e.g., pmb-warehouseModule) as the prefix. The final cache key format is evaluated as: <key-prefix>:<tenant-role>:<Entity>:<id> (for example: warehouse-service:public:User:123).
Automatic Invalidation: The controller layer invalidates the matching cache keys after each mutating REST/gRPC call, dispatched as a fire-and-forget background goroutine (cache.ClearPattern(...)) — not synchronous, so there's a small async window before a SCAN+DEL completes.
Direct Cache Usage
import "go-duck-preview/cache"
// Store a value for 10 minutes
cache.Set("my-key", myStruct, 10*time.Minute)
// Retrieve and deserialize -- returns a bool (found/not found), not an error
var target MyStruct
found := cache.Get("my-key", &target)
Valkey: The Open-Source Alternative
Every cache-aside repository, key-prefix rule, and invalidation path above works identically against Valkey — swap the config block and nothing else changes.
go-duck:
cache:
valkey:
enabled: true
host: "localhost:6379"
db: 0
ttl: "10m"
key-prefix: "warehouse-service"
Mutually exclusive: enabling both cache.redis.enabled and cache.valkey.enabled at generation time triggers a warning and Redis wins (Valkey is force-disabled). At runtime, if both are somehow left enabled, Valkey takes priority instead — don't rely on that edge case, pick one.
Live cache health — hit/miss counters, which engine is active, connection status, and reported version — is exposed on /api/system/metrics under the same system object as CPU/memory stats.