This guide will help you migrate from redistore v1 to v2, which introduces the Option Pattern for cleaner and more flexible initialization.
Version 2.0.0 is a breaking change that removes the old initialization functions in favor of a single, flexible NewStore() function with options.
Removed:
NewRediStore(size, network, address, username, password, keyPairs)NewRediStoreWithDB(size, network, address, username, password, db, keyPairs)NewRediStoreWithPool(pool, keyPairs)NewRediStoreWithURL(size, url, keyPairs)
Added:
NewStore(keyPairs, opts...)- Unified initialization with option pattern- 15+ configuration options (see Options Reference)
| v1 API | v2 API |
|---|---|
NewRediStore(10, "tcp", ":6379", "", "", []byte("key")) |
NewStore([][]byte{[]byte("key")}, WithAddress("tcp", ":6379")) |
NewRediStoreWithDB(10, "tcp", ":6379", "", "", "1", []byte("key")) |
NewStore([][]byte{[]byte("key")}, WithAddress("tcp", ":6379"), WithDB("1")) |
NewRediStoreWithURL(10, url, []byte("key")) |
NewStore([][]byte{[]byte("key")}, WithURL(url)) |
NewRediStoreWithPool(pool, []byte("key")) |
NewStore([][]byte{[]byte("key")}, WithPool(pool)) |
v1: Used variadic ...[]byte parameter
// Single key
NewRediStore(10, "tcp", ":6379", "", "", []byte("secret-key"))
// Multiple keys for rotation
NewRediStore(10, "tcp", ":6379", "", "",
[]byte("auth-key"), []byte("encrypt-key"),
[]byte("old-auth-key"), []byte("old-encrypt-key"))v2: Uses [][]byte slice with helper functions
// Recommended: Using KeysFromStrings (simplest)
NewStore(KeysFromStrings("secret-key"), WithAddress("tcp", ":6379"))
// Multiple keys for rotation
NewStore(
KeysFromStrings(
"auth-key", "encrypt-key",
"old-auth-key", "old-encrypt-key",
),
WithAddress("tcp", ":6379"),
)
// Alternative: Using Keys() with byte slices
NewStore(Keys([]byte("secret-key")), WithAddress("tcp", ":6379"))
// Direct slice syntax (still supported)
NewStore([][]byte{[]byte("secret-key")}, WithAddress("tcp", ":6379"))This change provides better type safety and clearer intent when passing multiple keys.
v2 introduces two convenience functions to simplify key pair creation:
KeysFromStrings(keys ...string)- Most convenient for development/testingKeys(keys ...[]byte)- When you already have byte slices
These helpers eliminate the need to write [][]byte{[]byte(...)} every time.
The import path changes to include /v2:
// v1
import "github.com/boj/redistore"
// v2
import "github.com/boj/redistore/v2"Update your go.mod:
go get github.com/boj/redistore/v2v1:
store, err := redistore.NewRediStore(
10, // pool size
"tcp", // network
":6379", // address
"", // username
"", // password
[]byte("secret-key"),
)v2:
store, err := redistore.NewStore(
redistore.KeysFromStrings("secret-key"),
redistore.WithAddress("tcp", ":6379"),
// WithPoolSize is optional (defaults to 10)
)v1:
store, err := redistore.NewRediStore(
10,
"tcp",
":6379",
"myuser", // username
"mypass", // password
[]byte("secret-key"),
)v2:
store, err := redistore.NewStore(
redistore.KeysFromStrings("secret-key"),
redistore.WithAddress("tcp", ":6379"),
redistore.WithAuth("myuser", "mypass"),
)
// Or just password:
store, err := redistore.NewStore(
redistore.KeysFromStrings("secret-key"),
redistore.WithAddress("tcp", ":6379"),
redistore.WithPassword("mypass"),
)v1:
store, err := redistore.NewRediStoreWithDB(
10,
"tcp",
":6379",
"",
"",
"5", // database
[]byte("secret-key"),
)v2:
store, err := redistore.NewStore(
redistore.KeysFromStrings("secret-key"),
redistore.WithAddress("tcp", ":6379"),
redistore.WithDB("5"),
)
// Or using integer:
store, err := redistore.NewStore(
redistore.KeysFromStrings("secret-key"),
redistore.WithAddress("tcp", ":6379"),
redistore.WithDBNum(5),
)v1:
store, err := redistore.NewRediStoreWithURL(
10,
"redis://:password@localhost:6379/0",
[]byte("secret-key"),
)v2:
store, err := redistore.NewStore(
[][]byte{[]byte("secret-key")},
redistore.WithURL("redis://:password@localhost:6379/0"),
)v1:
pool := &redis.Pool{
MaxIdle: 100,
IdleTimeout: 5 * time.Minute,
Dial: func() (redis.Conn, error) {
return redis.Dial("tcp", ":6379")
},
}
store, err := redistore.NewRediStoreWithPool(pool, []byte("secret-key"))v2 - Option A (Use existing pool):
pool := &redis.Pool{
MaxIdle: 100,
IdleTimeout: 5 * time.Minute,
Dial: func() (redis.Conn, error) {
return redis.Dial("tcp", ":6379")
},
}
store, err := redistore.NewStore(
[][]byte{[]byte("secret-key")},
redistore.WithPool(pool),
)v2 - Option B (Configure pool parameters):
store, err := redistore.NewStore(
redistore.KeysFromStrings("secret-key"),
redistore.WithAddress("tcp", ":6379"),
redistore.WithPoolSize(100),
redistore.WithIdleTimeout(5 * time.Minute),
)v1:
store, err := redistore.NewRediStore(10, "tcp", ":6379", "", "", []byte("secret-key"))
store.SetMaxLength(8192)
store.SetKeyPrefix("myapp_")
store.SetSerializer(redistore.JSONSerializer{})v2 (All at once):
store, err := redistore.NewStore(
redistore.KeysFromStrings("secret-key"),
redistore.WithAddress("tcp", ":6379"),
redistore.WithMaxLength(8192),
redistore.WithKeyPrefix("myapp_"),
redistore.WithSerializer(redistore.JSONSerializer{}),
)Note: You can still use
SetMaxLength(),SetKeyPrefix(), andSetSerializer()methods after creation in v2 if needed.
v1:
package main
import (
"github.com/boj/redistore"
"github.com/gorilla/sessions"
)
func main() {
store, err := redistore.NewRediStoreWithDB(
10,
"tcp",
"localhost:6379",
"user",
"password",
"1",
[]byte("secret-key-123"),
)
if err != nil {
panic(err)
}
defer store.Close()
// Configure after creation
store.SetMaxLength(8192)
store.SetKeyPrefix("myapp_")
store.SetMaxAge(86400 * 7) // 7 days
// Use store...
}v2:
package main
import (
"github.com/boj/redistore/v2"
"github.com/gorilla/sessions"
)
func main() {
store, err := redistore.NewStore(
[]byte("secret-key-123"),
redistore.WithAddress("tcp", "localhost:6379"),
redistore.WithAuth("user", "password"),
redistore.WithDB("1"),
redistore.WithMaxLength(8192),
redistore.WithKeyPrefix("myapp_"),
redistore.WithMaxAge(86400 * 7), // 7 days
)
if err != nil {
panic(err)
}
defer store.Close()
// Use store...
}WithPool(pool *redis.Pool) // Use custom pool
WithAddress(network, address string) // Connect via network + address
WithURL(url string) // Connect via Redis URLWithAuth(username, password string) // Set both username and password
WithPassword(password string) // Set password onlyWithDB(db string) // Database index as string ("0"-"15")
WithDBNum(dbNum int) // Database index as integer (0-15)
WithPoolSize(size int) // Connection pool size (default: 10)
WithIdleTimeout(timeout time.Duration) // Idle timeout (default: 240s)WithMaxLength(length int) // Max session size (default: 4096)
WithKeyPrefix(prefix string) // Redis key prefix (default: "session_")
WithDefaultMaxAge(age int) // Default TTL in seconds (default: 1200)
WithSerializer(s SessionSerializer) // Serializer (default: GobSerializer)
WithSessionOptions(opts *sessions.Options) // Full session options
WithPath(path string) // Cookie path (default: "/")
WithMaxAge(age int) // Cookie MaxAge (default: 30 days)Error:
store, err := redistore.NewStore(
[]byte{}, // ❌ Empty key pairs
redistore.WithAddress("tcp", ":6379"),
)
// Error: "at least one key pair is required"Fix:
store, err := redistore.NewStore(
[][]byte{[]byte("secret-key")}, // ✅ Provide key
redistore.WithAddress("tcp", ":6379"),
)Error:
store, err := redistore.NewStore(
[][]byte{[]byte("secret-key")},
redistore.WithMaxLength(8192), // ❌ No connection option
)
// Error: "exactly one connection option is required"Fix:
store, err := redistore.NewStore(
redistore.KeysFromStrings("secret-key"),
redistore.WithAddress("tcp", ":6379"), // ✅ Add connection option
redistore.WithMaxLength(8192),
)Error:
store, err := redistore.NewStore(
redistore.KeysFromStrings("secret-key"),
redistore.WithAddress("tcp", ":6379"), // ❌
redistore.WithURL("redis://localhost"), // ❌ Multiple connections
)
// Error: "only one connection option can be specified"Fix:
// Choose ONE connection method
store, err := redistore.NewStore(
redistore.KeysFromStrings("secret-key"),
redistore.WithAddress("tcp", ":6379"), // ✅ Only one
)After migrating, verify your application works correctly:
# Run your tests
go test ./...
# Check for compilation errors
go build ./...
# Run your application in development
go run main.goIf you need to rollback to v1:
-
Revert your
go.mod:go get github.com/boj/redistore@v1
-
Revert your code changes
-
Run
go mod tidy
- Issues: https://github.com/boj/redistore/issues
- Discussions: https://github.com/boj/redistore/discussions
- Documentation: https://pkg.go.dev/github.com/boj/redistore/v2
✅ Cleaner API - Single entry point, easier to understand ✅ More Flexible - Mix and match any configuration options ✅ Better Defaults - Sensible defaults for all settings ✅ Type Safety - Compile-time validation of options ✅ Extensible - Easy to add new options without breaking changes ✅ Self-Documenting - Option names clearly indicate what they configure