How to Configure Cache Settings with Redis for Production Deployments in AxonHub
To configure Redis cache settings for production deployments in AxonHub, set the CACHE_TYPE=redis environment variable and provide connection details via REDIS_ADDR, REDIS_PASSWORD, and REDIS_DB, then initialize the typed generic store from internal/pkg/xcache/redis/redis.go.
AxonHub provides a production-ready caching layer through its generic cache abstraction in looplj/axonhub. For high-throughput production environments, the Redis implementation offers typed operations, automatic tag handling, and configurable TTL support that outperforms in-memory alternatives.
Understanding AxonHub's Redis Cache Architecture
The caching system centers on the generic store interface defined in internal/pkg/xcache. The Redis-specific implementation in internal/pkg/xcache/redis/redis.go provides a typed cache store using Go generics, allowing you to cache specific struct types safely.
Key capabilities of the Redis store include:
- Generic type safety through
RedisStore[T]whereTis your payload type - Automatic tag management for bulk invalidation via Redis sets
- TTL support on both individual values and tag references
- Connection pooling via the underlying
go-redisclient
The configuration loader in conf/conf.go initializes the appropriate store implementation based on environment variables, creating the *redis.Client and passing it to the generic constructor.
Configuring Redis Connection Settings for Production
Production deployments require explicit environment variable configuration to activate Redis and set connection parameters. The configuration loader expects specific variables that map to redis.Options fields.
Set the following environment variables before starting AxonHub:
# Required: Enable Redis backend
export CACHE_TYPE=redis
# Required: Redis server address
export REDIS_ADDR=redis-prod.example.com:6379
# Optional: Authentication
export REDIS_PASSWORD=your-secure-password
# Optional: Database index (default 0)
export REDIS_DB=0
# Production tuning: Connection pool
export REDIS_POOL_SIZE=20
# Production tuning: Timeouts
export REDIS_DIAL_TIMEOUT=5s
export REDIS_READ_TIMEOUT=3s
export REDIS_WRITE_TIMEOUT=3s
In conf/conf.go, the buildCacheStore function processes these variables to construct the client:
// conf/conf.go (excerpt)
func buildCacheStore(cfg *Config) (xcache.Store, error) {
switch cfg.Cache.Type {
case "redis":
rdb := redis.NewClient(&redis.Options{
Addr: cfg.Cache.Redis.Addr,
Password: cfg.Cache.Redis.Password,
DB: cfg.Cache.Redis.DB,
PoolSize: cfg.Cache.Redis.PoolSize,
DialTimeout: cfg.Cache.Redis.DialTimeout,
})
return redis.NewRedisStore[MyData](rdb), nil
}
}
Implementing Typed Redis Cache Stores
After configuration, instantiate typed cache stores for your specific data structures. The generic implementation in internal/pkg/xcache/redis/redis.go requires a concrete type parameter.
Example implementation for caching UserProfile structs:
package cache
import (
"os"
"time"
"github.com/looplj/axonhub/internal/pkg/xcache/redis"
"github.com/redis/go-redis/v9"
)
type UserProfile struct {
ID string `json:"id"`
Name string `json:"name"`
Email string `json:"email"`
}
func NewUserProfileCache() (*redis.RedisStore[UserProfile], error) {
rdb := redis.NewClient(&redis.Options{
Addr: os.Getenv("REDIS_ADDR"),
Password: os.Getenv("REDIS_PASSWORD"),
DB: 0,
PoolSize: 10,
DialTimeout: 5 * time.Second,
})
store := redis.NewRedisStore[UserProfile](rdb)
return store, nil
}
Usage in application handlers:
func GetUserProfile(ctx context.Context, uid string) (*UserProfile, error) {
cache, _ := NewUserProfileCache()
// Attempt cache retrieval
if cached, err := cache.Get(ctx, uid); err == nil {
return cached, nil
}
// Database fallback
profile, err := dbFetchUser(uid)
if err != nil {
return nil, err
}
// Cache with 30-minute TTL and invalidation tag
_ = cache.Set(ctx, uid, profile,
cache.WithExpiration(30*time.Minute),
cache.WithTags([]string{"user_profiles"}))
return profile, nil
}
Production Deployment Best Practices
When deploying AxonHub with Redis in production environments, configure additional resilience and security parameters beyond basic connection settings.
Connection Resilience and Timeouts
Set explicit timeouts to prevent goroutine leaks during network partitions:
export REDIS_DIAL_TIMEOUT=5s
export REDIS_READ_TIMEOUT=3s
export REDIS_WRITE_TIMEOUT=3s
export REDIS_POOL_SIZE=20
These map directly to redis.Options fields in conf/conf.go and ensure the connection pool behaves predictably under load.
TLS Encryption
For production deployments requiring encrypted connections, extend the configuration to include TLS certificates:
// Production TLS configuration
import "crypto/tls"
func buildTLSRedisClient(cfg *Config) *redis.Client {
return redis.NewClient(&redis.Options{
Addr: cfg.Cache.Redis.Addr,
Password: cfg.Cache.Redis.Password,
TLSConfig: &tls.Config{
MinVersion: tls.VersionTLS12,
},
PoolSize: cfg.Cache.Redis.PoolSize,
})
}
Health Monitoring and Graceful Shutdown
Implement health checks using the Redis ping command, and ensure proper client cleanup during shutdown:
// Health check
func (s *Server) HealthCheck(ctx context.Context) error {
return s.cacheStore.Client().Ping(ctx).Err()
}
// Graceful shutdown
func (s *Server) Shutdown() {
if s.cacheStore != nil {
s.cacheStore.Client().Close()
}
}
High Availability Clustering
For Redis Cluster deployments, modify the connection initialization to use redis.NewClusterClient instead of redis.NewClient. The internal/pkg/xcache/redis/redis.go implementation works with both because it depends on the RedisClientInterface abstraction rather than concrete client types.
Cache Invalidation and Tag Management
AxonHub's Redis implementation supports tag-based invalidation through Redis sets, enabling bulk cache clearing without iterating individual keys.
The tag system stores references under keys following the pattern gocache_tag_<tag>. When you invalidate a tag, the system removes all associated values.
Example of bulk invalidation:
func InvalidateUserProfiles(ctx context.Context) error {
cache, _ := NewUserProfileCache()
// Retrieve all keys associated with the tag
tagKey := fmt.Sprintf("gocache_tag_%s", "user_profiles")
members, err := cache.Client().SMembers(ctx, tagKey).Result()
if err != nil {
return err
}
// Delete individual cache entries
for _, key := range members {
_ = cache.Delete(ctx, key)
}
// Clean up the tag set itself
return cache.Client().Del(ctx, tagKey).Err()
}
For full cache resets (e.g., during deployments), use the Clear method which executes FLUSHALL:
// Use with caution in production - clears entire Redis instance
func ClearAllCaches(ctx context.Context) error {
cache, _ := NewUserProfileCache()
return cache.Clear(ctx)
}
Summary
Configuring Redis cache settings for production deployments in AxonHub requires:
- Setting the cache type to
redisvia theCACHE_TYPEenvironment variable to activate the Redis backend inconf/conf.go - Providing connection parameters including
REDIS_ADDR,REDIS_PASSWORD, andREDIS_DBto establish the client ininternal/pkg/xcache/redis/redis.go - Tuning production options such as
REDIS_POOL_SIZE,REDIS_DIAL_TIMEOUT, and TLS configuration for connection resilience and security - Implementing typed stores using the generic
RedisStore[T]to ensure type-safe cache operations with automatic JSON marshaling - Managing invalidation through tag-based clearing or
FLUSHALLoperations for cache consistency during updates
Frequently Asked Questions
How do I switch from in-memory cache to Redis in AxonHub?
Set the environment variable CACHE_TYPE=redis before starting the application. The configuration loader in conf/conf.go detects this value and initializes the Redis client instead of the default in-memory store. You must also provide REDIS_ADDR pointing to your Redis server endpoint.
What Redis version is required for AxonHub production deployments?
AxonHub uses the go-redis/v9 client library, which supports Redis versions 5.0 and above. For production deployments, Redis 6.0 or later is recommended to leverage TLS encryption and improved ACL support for authentication.
How does AxonHub handle Redis connection failures in production?
The internal/pkg/xcache/redis/redis.go implementation returns errors from underlying Redis commands, allowing your application to implement fallback logic. For connection resilience, configure REDIS_DIAL_TIMEOUT, REDIS_READ_TIMEOUT, and REDIS_WRITE_TIMEOUT in your environment variables to prevent indefinite blocking during network partitions.
Can I use Redis Cluster with AxonHub for high availability?
Yes. While the basic configuration uses redis.NewClient for single-node deployments, the RedisStore in internal/pkg/xcache/redis/redis.go depends on the RedisClientInterface abstraction, which is compatible with redis.NewClusterClient. For clustered deployments, modify the initialization in conf/conf.go to use the cluster client with your REDIS_CLUSTER_NODES configuration.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →