# How to Configure Cache Settings with Redis for Production Deployments in AxonHub

> Learn to configure Redis cache settings for AxonHub production deployments. Set environment variables and initialize your store for optimal performance. Explore the Redis cache setup.

- Repository: [Loop/axonhub](https://github.com/looplj/axonhub)
- Tags: how-to-guide
- Published: 2026-03-06

---

**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`](https://github.com/looplj/axonhub/blob/main/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`](https://github.com/looplj/axonhub/blob/main/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]` where `T` is 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-redis` client

The configuration loader in [`conf/conf.go`](https://github.com/looplj/axonhub/blob/main/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:

```bash

# 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`](https://github.com/looplj/axonhub/blob/main/conf/conf.go), the `buildCacheStore` function processes these variables to construct the client:

```go
// 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`](https://github.com/looplj/axonhub/blob/main/internal/pkg/xcache/redis/redis.go) requires a concrete type parameter.

Example implementation for caching `UserProfile` structs:

```go
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:

```go
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:

```bash
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`](https://github.com/looplj/axonhub/blob/main/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:

```go
// 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:

```go
// 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`](https://github.com/looplj/axonhub/blob/main/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:

```go
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`:

```go
// 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 `redis` via the `CACHE_TYPE` environment variable to activate the Redis backend in [`conf/conf.go`](https://github.com/looplj/axonhub/blob/main/conf/conf.go)
- **Providing connection parameters** including `REDIS_ADDR`, `REDIS_PASSWORD`, and `REDIS_DB` to establish the client in [`internal/pkg/xcache/redis/redis.go`](https://github.com/looplj/axonhub/blob/main/internal/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 `FLUSHALL` operations 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`](https://github.com/looplj/axonhub/blob/main/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`](https://github.com/looplj/axonhub/blob/main/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`](https://github.com/looplj/axonhub/blob/main/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`](https://github.com/looplj/axonhub/blob/main/conf/conf.go) to use the cluster client with your `REDIS_CLUSTER_NODES` configuration.