How to Use go-redis for Caching and Sessions in Go

Use the `go-redis` client to manage caching and sessions by treating Redis as a key-value store with configurable expiration times, leveraging its `Set` and `Get` methods for data retrieval and `Expire` for automatic cleanup.

Use the go-redis client to manage caching and sessions by treating Redis as a key-value store with configurable expiration times, leveraging its Set and Get methods for data retrieval and Expire for automatic cleanup. For sessions, store serialized user data with a unique session ID as the key and set a TTL to handle logout or timeout automatically.

Here is a practical implementation pattern for both use cases:

package main

import (
	"context"
	"encoding/json"
	"fmt"
	"time"

	"github.com/redis/go-redis/v9"
)

// Session represents user session data
type Session struct {
	UserID   string `json:"user_id"`
	Role     string `json:"role"`
	LoggedIn time.Time `json:"logged_in"`
}

func main() {
	ctx := context.Background()
	// Initialize client
	rdb := redis.NewClient(&redis.Options{
		Addr:     "localhost:6379",
		Password: "", // no password set
		DB:       0,  // use default DB
	})

	// 1. Caching Example: Store expensive query result
	cacheKey := "user:profile:123"
	cachedData, err := rdb.Get(ctx, cacheKey).Result()
	if err == redis.Nil {
		// Cache miss: fetch from DB (simulated)
		data := "Fetched from database for user 123"
		// Set with 1 hour expiration
		err = rdb.Set(ctx, cacheKey, data, time.Hour).Err()
		if err != nil {
			panic(err)
		}
		fmt.Println("Cache miss, data stored.")
	} else if err != nil {
		panic(err)
	} else {
		fmt.Println("Cache hit:", cachedData)
	}

	// 2. Session Example: Create and retrieve session
	sessionID := "sess_abc123"
	session := Session{
		UserID:   "user_456",
		Role:     "admin",
		LoggedIn: time.Now(),
	}

	// Serialize session to JSON
	sessionData, _ := json.Marshal(session)
	// Store session with 30-minute TTL
	err = rdb.Set(ctx, sessionID, string(sessionData), 30*time.Minute).Err()
	if err != nil {
		panic(err)
	}

	// Retrieve and deserialize session
	val, err := rdb.Get(ctx, sessionID).Result()
	if err != nil {
		panic(err)
	}
	var retrievedSession Session
	json.Unmarshal([]byte(val), &retrievedSession)
	fmt.Printf("Session retrieved for user: %s, Role: %s\n", retrievedSession.UserID, retrievedSession.Role)

	// Cleanup: Delete session on logout
	rdb.Del(ctx, sessionID)
}

Key considerations for production:

  • Always check for redis.Nil to distinguish between a cache miss and a connection error.
  • Use Set with a duration argument (e.g., time.Hour) to automatically expire keys, preventing stale data.
  • For sessions, ensure the session ID is cryptographically secure (e.g., using crypto/rand) to prevent session hijacking.
  • Wrap Redis calls in a context to respect request timeouts and cancellations.
  • Use connection pooling (default in go-redis) to handle high concurrency efficiently.