Redistore
A session store backend for gorilla/sessions using Redis.
Install / Use
/learn @boj/RedistoreREADME
redistore
A session store backend for gorilla/sessions with Redis as the storage engine.
Features
- ✨ Clean API - Single entry point with flexible option pattern
- 🔧 Highly Configurable - 15+ options for fine-grained control
- 🔒 Secure - Built on gorilla/sessions with secure cookie encoding
- ⚡ Fast - Redis-backed for high performance
- 📦 Serialization - Support for Gob and JSON serializers
- 🧪 Well Tested - Comprehensive test coverage
Requirements
- Go: 1.23 or higher
- Redis: 6.x or 7.x
- Dependencies:
- Redigo - Redis client
- gorilla/sessions - Session management
- gorilla/securecookie - Secure cookies
Installation
For v2 (Recommended)
go get github.com/boj/redistore/v2
For v1 (Legacy)
go get github.com/boj/redistore@v1
Note: v2 introduces a cleaner API with the Option Pattern. See MIGRATION.md for upgrade instructions.
Quick Start
package main
import (
"log"
"net/http"
"github.com/boj/redistore/v2"
"github.com/gorilla/sessions"
)
func main() {
// Create a new store with options
store, err := redistore.NewStore(
redistore.KeysFromStrings("secret-key"),
redistore.WithAddress("tcp", ":6379"),
)
if err != nil {
panic(err)
}
defer store.Close()
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
// Get a session
session, err := store.Get(r, "session-key")
if err != nil {
log.Println(err.Error())
return
}
// Set a value
session.Values["foo"] = "bar"
// Save session
if err = sessions.Save(r, w); err != nil {
log.Fatalf("Error saving session: %v", err)
}
})
log.Fatal(http.ListenAndServe(":8080", nil))
}
Documentation
- API Reference: pkg.go.dev/github.com/boj/redistore/v2
- Migration Guide: MIGRATION.md
- Changelog: CHANGELOG.md
- gorilla/sessions: Documentation
Usage Examples
Basic Connection
store, err := redistore.NewStore(
redistore.KeysFromStrings("secret-key"),
redistore.WithAddress("tcp", "localhost:6379"),
)
With Authentication
store, err := redistore.NewStore(
redistore.KeysFromStrings("secret-key"),
redistore.WithAddress("tcp", "localhost:6379"),
redistore.WithAuth("username", "password"),
)
Specific Database
store, err := redistore.NewStore(
redistore.KeysFromStrings("secret-key"),
redistore.WithAddress("tcp", "localhost:6379"),
redistore.WithDB("5"), // Use database 5
)
Using Redis URL
store, err := redistore.NewStore(
redistore.KeysFromStrings("secret-key"),
redistore.WithURL("redis://:password@localhost:6379/0"),
)
Custom Configuration
store, err := redistore.NewStore(
redistore.KeysFromStrings("secret-key"),
redistore.WithAddress("tcp", "localhost:6379"),
redistore.WithMaxLength(8192), // Max session size: 8KB
redistore.WithKeyPrefix("myapp_"), // Key prefix
redistore.WithDefaultMaxAge(3600), // Default TTL: 1 hour
redistore.WithSerializer(redistore.JSONSerializer{}), // JSON serializer
)
Using a Custom Pool
import "github.com/gomodule/redigo/redis"
pool := &redis.Pool{
MaxIdle: 100,
IdleTimeout: 5 * time.Minute,
Dial: func() (redis.Conn, error) {
return redis.Dial("tcp", "localhost:6379")
},
}
store, err := redistore.NewStore(
redistore.KeysFromStrings("secret-key"),
redistore.WithPool(pool),
)
Key Rotation
Support for encryption key rotation allows you to change keys without invalidating existing sessions:
// Keys are provided in pairs: authentication key, encryption key
// The first pair is used for encoding new sessions
// All pairs are tried for decoding existing sessions
store, err := redistore.NewStore(
redistore.KeysFromStrings(
"new-authentication-key", // 32 or 64 bytes recommended
"new-encryption-key", // 16, 24, or 32 bytes for AES
"old-authentication-key", // Keep for existing sessions
"old-encryption-key", // Keep for existing sessions
),
redistore.WithAddress("tcp", "localhost:6379"),
)
// Using Keys() with byte slices for production
authKey, _ := loadKeyFromSecureStorage("auth-key")
encryptKey, _ := loadKeyFromSecureStorage("encrypt-key")
store, err := redistore.NewStore(
redistore.Keys(authKey, encryptKey),
redistore.WithAddress("tcp", "localhost:6379"),
)
Key Sizes:
- Authentication key: 32 or 64 bytes (HMAC)
- Encryption key: 16 (AES-128), 24 (AES-192), or 32 bytes (AES-256)
Rotation Process:
- Add new key pair at the beginning
- Keep old keys for a transition period
- Remove old keys once all sessions have been renewed
Helper Functions:
KeysFromStrings(keys ...string)- Simplest way to provide keys from stringsKeys(keys ...[]byte)- For keys already as byte slices- Direct slice:
[][]byte{[]byte("key")}- Original syntax still supported
Complete Example
package main
import (
"log"
"net/http"
"github.com/boj/redistore/v2"
"github.com/gorilla/sessions"
)
func main() {
// Initialize store with custom configuration
store, err := redistore.NewStore(
redistore.KeysFromStrings("secret-key-123"),
redistore.WithAddress("tcp", "localhost:6379"),
redistore.WithDB("1"),
redistore.WithMaxLength(8192),
redistore.WithKeyPrefix("webapp_"),
redistore.WithDefaultMaxAge(3600), // 1 hour
)
if err != nil {
log.Fatal(err)
}
defer store.Close()
http.HandleFunc("/set", func(w http.ResponseWriter, r *http.Request) {
session, _ := store.Get(r, "my-session")
session.Values["user"] = "john_doe"
session.Values["authenticated"] = true
sessions.Save(r, w)
w.Write([]byte("Session saved!"))
})
http.HandleFunc("/get", func(w http.ResponseWriter, r *http.Request) {
session, _ := store.Get(r, "my-session")
user := session.Values["user"]
if user != nil {
w.Write([]byte("User: " + user.(string)))
} else {
w.Write([]byte("No user in session"))
}
})
http.HandleFunc("/delete", func(w http.ResponseWriter, r *http.Request) {
session, _ := store.Get(r, "my-session")
session.Options.MaxAge = -1
sessions.Save(r, w)
w.Write([]byte("Session deleted!"))
})
log.Println("Server started on :8080")
log.Fatal(http.ListenAndServe(":8080", nil))
}
Configuration Options
Connection Options (Required - Choose ONE)
| Option | Description |
| ------------------------------- | -------------------------------------------------------- |
| WithPool(pool) | Use a custom Redis connection pool |
| WithAddress(network, address) | Connect via network and address (e.g., "tcp", ":6379") |
| WithURL(url) | Connect via Redis URL (e.g., "redis://localhost:6379/0") |
Authentication Options
| Option | Description |
| ------------------------------ | ------------------------- |
| WithAuth(username, password) | Set username and password |
| WithPassword(password) | Set password only |
Redis Configuration
| Option | Default | Description |
| -------------------------- | ------- | ------------------------- |
| WithDB(db) | "0" | Database index ("0"-"15") |
| WithDBNum(dbNum) | 0 | Database index as integer |
| WithPoolSize(size) | 10 | Connection pool size |
| WithIdleTimeout(timeout) | 240s | Connection idle timeout |
Store Configuration
| Option | Default | Description |
| -------------------------- | ------------- | ----------------------------------------- |
| WithMaxLength(length) | 4096 | Max session size in bytes (0 = unlimited) |
| WithKeyPrefix(prefix) | "session_" | Redis key prefix |
| WithDefaultMaxAge(age) | 1200 | Default TTL in seconds (20 minutes) |
| WithSerializer(s) | GobSerializer | Session serializer |
| WithSessionOptions(opts) | - | Full gorilla/sessions options |
| WithPath(path) | "/" | Cookie path |
| WithMaxAge(age) | 30 days | Cookie MaxAge |
Serializers
Gob Serializer (Default)
Uses Go's encoding/gob package. Efficient binary format, suitable for complex Go types.
store, err := redistore.NewStore(
[][]byte{[]byte("secret-ke
Related Skills
node-connect
342.5kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
85.3kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
342.5kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
qqbot-media
342.5kQQBot 富媒体收发能力。使用 <qqmedia> 标签,系统根据文件扩展名自动识别类型(图片/语音/视频/文件)。
