Cache
Nimbus provides a unified caching API with support for memory, Redis, Memcached, DynamoDB, and Cloudflare KV. Call cache.Boot(nil) in your server boot to initialize from .env.
Documentation
Detailed guides:
Remember (getOrSet)
The most common pattern: try cache first, otherwise compute, store, and return.
// Boot in bin/server.go (uses CACHE_DRIVER from .env)
cache.Boot(nil)
user, err := cache.RememberT("user:1", 10*time.Minute, func() (User, error) {
var u User
err := database.Get().First(&u, 1).Error
return u, err
})
Get, Set, Has, Missing, Pull
Use Get and Set when you need more control. Has / Missing check existence without fetching. Pull retrieves and deletes in one call (e.g. flash messages).
cache.Set("app:settings", map[string]any{"theme": "dark"}, 5*time.Minute)
settings, ok := cache.Get("app:settings")
cache.SetForever("app:version", "2.0.0") // never expires
if cache.Has("products:featured") { /* key exists */ }
token, ok := cache.Pull("verify:token:123") // get and delete
Namespaces
Group related keys under a prefix and clear them together.
usersCache := cache.Namespace("users")
usersCache.Set("42", user, 10*time.Minute) // stores under "users:42"
usersCache.Clear() // clears all "users:*"
Configuration
Set CACHE_DRIVER in .env. Supported: memory, redis, memcached, dynamodb, cloudflare.
| Driver | Env vars |
|---|---|
memory | (default, no config) |
redis | REDIS_URL (e.g. redis://localhost:6379) |
memcached | MEMCACHED_SERVERS (e.g. localhost:11211) |
dynamodb | CACHE_DYNAMO_TABLE, AWS_REGION, AWS credentials |
cloudflare | CLOUDFLARE_ACCOUNT_ID, CLOUDFLARE_NAMESPACE_ID, CLOUDFLARE_API_TOKEN |
Real-Life Example: API Response Caching
func (ctrl *ProductController) Index(c *http.Context) error {
page := c.QueryInt("page", 1)
key := fmt.Sprintf("products:page:%d", page)
products, err := cache.RememberT[[]Product](key, 5*time.Minute, func() ([]Product, error) {
var products []Product
err := db.Scopes(database.Paginate(page, 20)).
Preload("Category").
Find(&products).Error
return products, err
})
if err != nil {
return err
}
return c.JSON(200, products)
}
Real-Life Example: Cache Invalidation on Update
func (ctrl *ProductController) Update(c *http.Context) error {
id := c.Param("id")
// ... validate and update product ...
// Invalidate specific cache entry
cache.Delete(fmt.Sprintf("product:%s", id))
// Invalidate related listing caches
productsCache := cache.Namespace("products")
productsCache.Clear() // Clear all product listing pages
return c.JSON(200, product)
}
Real-Life Example: Rate Limiting with Cache
func checkRateLimit(ip string, limit int) bool {
key := fmt.Sprintf("ratelimit:%s", ip)
val, ok := cache.Get(key)
if !ok {
cache.Set(key, 1, time.Minute)
return true // First request
}
count := val.(int)
if count >= limit {
return false // Exceeded
}
cache.Set(key, count+1, time.Minute)
return true
}
Best Practices
- Use
Remember/RememberTto eliminate cache stampede - Choose TTL carefully — too short wastes compute; too long serves stale data
- Invalidate on writes — always clear cache when underlying data changes
- Use namespaces — group related keys for easy bulk invalidation
- Use Memory for dev, Redis for prod — switch via
CACHE_DRIVERenv var - Include user/tenant IDs in cache keys to prevent data leakage