Deterministic. Minimal. Fast. A tiny, thread-safe in-memory key-value cache with per-key TTL and a background janitor. Think of it as a small Redis-flavored TTL cache for Go: set bytes, get bytes, optional capacity, predictable eviction.
Note: This is the only public repository we are publishing; historically we had no public repositories. We are open to contributions and feedback. But we don't public.
go get github.com/goverta/cache
package main
import (
"time"
"github.com/goverta/cache"
)
func main() {
c := cache.New(cache.Options{JanitorInterval: 500 * time.Millisecond, MaxEntries: 0})
defer c.Close()
c.Set("token", []byte("abc123"), 2*time.Second)
v, ok := c.Get("token")
_, _ = v, ok
}
- Thread-safe operations with
sync.RWMutex
- Per-key TTL with wall-clock semantics
- Background janitor that evicts expired keys on a ticker
- Optional capacity via FIFO eviction (
MaxEntries
), simple and predictable - No external dependencies, pure stdlib
- Copy-on-write and copy-on-read to avoid aliasing
type Options struct {
JanitorInterval time.Duration
MaxEntries int
}
func New(opts Options) *cache.Cache
func (*Cache) Set(key string, value []byte, ttl time.Duration) bool
func (*Cache) Get(key string) ([]byte, bool)
func (*Cache) Delete(key string) bool
func (*Cache) Len() int
func (*Cache) Keys() []string
func (*Cache) PurgeExpired()
func (*Cache) Close()
- Set overwrites existing values and returns true
- TTL=0 means no expiry
- Get only returns non-expired values
- Keys/Len exclude expired entries
- Expired entries are removed by janitor or
PurgeExpired()
- If
MaxEntries>0
, oldest insertions are evicted first (simple FIFO). Overwrites append a new position in the queue; eviction always removes the oldest still-present key.
- Storage:
map[string]item{value []byte, expiry time.Time}
- Capacity: append-only FIFO with lazy duplicates; compacted when queue grows > 2× live keys
- Expiry policy: lazy on read, proactive via janitor, explicit via
PurgeExpired
- Time source:
time.Now()
- Determinism: no randomized eviction; straightforward FIFO and TTL
// Capacity-bounded cache
c := cache.New(cache.Options{JanitorInterval: 100 * time.Millisecond, MaxEntries: 1024})
defer c.Close()
// Session token with TTL
c.Set("sess:123", []byte("..."), 15*time.Minute)
// Periodic purge if janitor disabled
c.PurgeExpired()
- Reads use RLock and copy result to avoid aliasing
- Writes Lock once, FIFO eviction is O(1) amortized with lazy compaction
- For read-heavy workloads, increase
GOMAXPROCS
and keepMaxEntries
unbounded or sufficiently high - Benchmarks included; run with
-bench
flags
- Thread-safe via
sync.RWMutex
- Per-key TTL using wall clock
- Optional capacity via FIFO eviction
- No external dependencies
go test -bench . -benchmem
Included:
- Set/Get no TTL
- Set/Get with short TTL
- Parallel Get on prewarmed keys
- LRU option
- Metrics hooks
- Sharding for higher parallelism
go test -run Example