SkillAgentSearch skills...

Cache

A multi-driver caching library for Go that makes swapping cache backends trivial without changing application code.

Install / Use

/learn @goforj/Cache
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

<p align="center"> <img src="./docs/images/logo.png?v=1" width="300" alt="cache logo"> </p> <p align="center"> cache gives your services one cache API with multiple backend options. Swap drivers without refactoring. </p> <p align="center"> <a href="https://pkg.go.dev/github.com/goforj/cache"><img src="https://pkg.go.dev/badge/github.com/goforj/cache.svg" alt="Go Reference"></a> <a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="License: MIT"></a> <a href="https://golang.org"><img src="https://img.shields.io/badge/go-1.24+-blue?logo=go" alt="Go version"></a> <img src="https://img.shields.io/github/v/tag/goforj/cache?label=version&sort=semver" alt="Latest tag"> <a href="https://goreportcard.com/report/github.com/goforj/cache"><img src="https://goreportcard.com/badge/github.com/goforj/cache" alt="Go Report Card"></a> <a href="https://codecov.io/gh/goforj/cache"><img src="https://codecov.io/gh/goforj/cache/graph/badge.svg?token=B6ROULLKWU"/></a> <!-- test-count:embed:start --> <img src="https://img.shields.io/badge/unit_tests-187-brightgreen" alt="Unit tests (executed count)"> <img src="https://img.shields.io/badge/integration_tests-113-blue" alt="Integration tests (executed count)"> <!-- test-count:embed:end --> </p>

What cache is

An explicit cache abstraction with a minimal Store interface and ergonomic Cache helpers. Drivers are chosen when you construct the store, so swapping backends is a dependency-injection change instead of a refactor.

Installation

go get github.com/goforj/cache

Optional backends are separate modules. Install only what you use:

go get github.com/goforj/cache/driver/rediscache
go get github.com/goforj/cache/driver/memcachedcache
go get github.com/goforj/cache/driver/natscache
go get github.com/goforj/cache/driver/dynamocache
go get github.com/goforj/cache/driver/sqlitecache
go get github.com/goforj/cache/driver/postgrescache
go get github.com/goforj/cache/driver/mysqlcache

Drivers

| Driver / Backend | Mode | Shared | Durable | TTL | Counters | Locks | RateLimit | Prefix | Batch | Shaping | Notes | |-------------------------------------------------------------------------------------------------------------:| :--- | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :--- | | <img src="https://img.shields.io/badge/null-9e9e9e?logo=probot&logoColor=white" alt="Null"> | No-op | - | - | - | - | No-op | No-op | ✓ | ✓ | ✓ | Great for tests: cache calls are no-ops and never persist. | | <img src="https://img.shields.io/badge/file-3f51b5?logo=files&logoColor=white" alt="File"> | Local filesystem | - | ✓ | ✓ | ✓ | Local | Local | - | ✓ | ✓ | Simple durability on a single host; set StoreConfig.FileDir (or use NewFileStore). | | <img src="https://img.shields.io/badge/memory-5c5c5c?logo=cachet&logoColor=white" alt="Memory"> | In-process | - | - | ✓ | ✓ | Local | Local | - | ✓ | ✓ | Fastest; per-process only, best for single-node or short-lived data. | | <img src="https://img.shields.io/badge/memcached-0198c4?logo=buffer&logoColor=white" alt="Memcached"> | Networked | ✓ | - | ✓ | ✓ | Shared | Shared | ✓ | ✓ | ✓ | TTL resolution is 1s; configure addresses via memcachedcache.Config.Addresses. | | <img src="https://img.shields.io/badge/redis-%23DC382D?logo=redis&logoColor=white" alt="Redis"> | Networked | ✓ | - | ✓ | ✓ | Shared | Shared | ✓ | ✓ | ✓ | Full feature set; counters refresh TTL (Redis counter TTL granularity currently 1s). | | <img src="https://img.shields.io/badge/nats-27AAE1?logo=natsdotio&logoColor=white" alt="NATS"> | Networked | ✓ | - | ✓ | ✓ | Shared | Shared | ✓ | ✓ | ✓ | JetStream KV-backed driver; inject an existing bucket via natscache.Config.KeyValue. | | <img src="https://img.shields.io/badge/dynamodb-4053D6?logo=amazon-dynamodb&logoColor=white" alt="DynamoDB"> | Networked | ✓ | ✓ | ✓ | ✓ | Shared | Shared | ✓ | ✓ | ✓ | Backed by DynamoDB (supports localstack/dynamodb-local). | | <img src="https://img.shields.io/badge/sqlite-003B57?logo=sqlite&logoColor=white" alt="SQLite"> | Local / file | - | ✓ | ✓ | ✓ | Local | Local | ✓ | ✓ | ✓ | sqlitecache (via sqlcore); great for embedded/local durable cache. | | <img src="https://img.shields.io/badge/postgres-336791?logo=postgresql&logoColor=white" alt="Postgres"> | Networked | ✓ | ✓ | ✓ | ✓ | Shared | Shared | ✓ | ✓ | ✓ | postgrescache (via sqlcore); good shared durable backend. | | <img src="https://img.shields.io/badge/mysql-4479A1?logo=mysql&logoColor=white" alt="MySQL"> | Networked | ✓ | ✓ | ✓ | ✓ | Shared | Shared | ✓ | ✓ | ✓ | mysqlcache (via sqlcore); good shared durable backend. |

Driver constructor quick examples

Use root constructors for in-process backends, and driver-module constructors for external backends. Driver backends live in separate modules so applications only import/link the optional backend dependencies they actually use.

package main

import (
	"context"
	"fmt"
	"time"

	"github.com/goforj/cache"
	"github.com/goforj/cache/cachecore"
	"github.com/goforj/cache/driver/dynamocache"
	"github.com/goforj/cache/driver/memcachedcache"
	"github.com/goforj/cache/driver/mysqlcache"
	"github.com/goforj/cache/driver/natscache"
	"github.com/goforj/cache/driver/postgrescache"
	"github.com/goforj/cache/driver/rediscache"
	"github.com/goforj/cache/driver/sqlitecache"
)

func main() {
	ctx := context.Background()
	base := cachecore.BaseConfig{DefaultTTL: 5 * time.Minute, Prefix: "app"}

	cache.NewMemoryStore(ctx)               // in-process memory
	cache.NewFileStore(ctx, "./cache-data") // local file-backed
	cache.NewNullStore(ctx)                 // disabled / drop-only

	// Redis (driver-owned connection config; no direct redis client required)
	redisStore := rediscache.New(rediscache.Config{BaseConfig: base, Addr: "127.0.0.1:6379"})
	_ = redisStore

	// Memcached (one or more server addresses)
	memcachedStore := memcachedcache.New(memcachedcache.Config{
		BaseConfig: base,
		Addresses:  []string{"127.0.0.1:11211"},
	})
	_ = memcachedStore

	// NATS JetStream KV (inject a bucket from your NATS setup)
	var kv natscache.KeyValue // create via your NATS JetStream setup
	natsStore := natscache.New(natscache.Config{BaseConfig: base, KeyValue: kv})
	_ = natsStore

	// DynamoDB (auto-creates client when Client is nil)
	dynamoStore, err := dynamocache.New(ctx, dynamocache.Config{
		BaseConfig: base,
		Region:     "us-east-1",
		Table:      "cache_entries",
	})
	fmt.Println(dynamoStore, err)

	// SQLite (via sqlcore)
	sqliteStore, err := sqlitecache.New(sqlitecache.Config{
		BaseConfig: base,
		DSN:        "file::memory:?cache=shared",
		Table:      "cache_entries",
	})
	fmt.Println(sqliteStore, err)

	// Postgres (via sqlcore)
	postgresStore, err := postgrescache.New(postgrescache.Config{
		BaseConfig: base,
		DSN:        "postgres://user:pass@127.0.0.1:5432/app?sslmode=disable",
		Table:      "cache_entries",
	})
	fmt.Println(postgresStore, err)

	// MySQL (via sqlcore)
	mysqlStore, err := mysqlcache.New(mysqlcache.Config{
		BaseConfig: base,
		DSN:        "user:pass@tcp(127.0.0.1:3306)/app?parseTime=true",
		Table:      "cache_entries",
	})
	fmt.Println(mysqlStore, err)
}

Module Layout

| Category | Module | Purpose | | --- | --- | --- | | Core | github.com/goforj/cache | Cache API and root-backed stores (memory, file, null) | | Core | github.com/goforj/cache/cachecore | Shared contracts, types, and base config | | Core | github.com/goforj/cache/cachetest | Shared store contract test harness | | Optional drivers | github.com/goforj/cache/driver/*cache | Backend driver modules | | Optional drivers | github.com/goforj/cache/driver/sqlcore | Shared SQL implementation for dialect wrappers | | Testing and tooling | github.com/goforj/cache/integration | Integration suites (root, all) | | Testing and tooling | github.com/goforj/cache/docs | Docs + benchmark tooling |

Quick Start

import (
    "context"
    "fmt"
    "time"

    "github.com/goforj/cache"
    "github.com/goforj/cache/cachecore"
    "github.com/goforj/cache/driver/rediscache"
)

func main() {
    ctx := context.Background()

    store := cache.NewMemoryStoreWithConfig(ctx, cache.StoreConfig{
        BaseConfig: cachecore.BaseConfig{DefaultTTL: 5 * time.Minute},
    })
    c := cache.NewCache(store)

    type Profile struct { Name string `json:"name"` }

    // Typed lifecycle (generic helpers): set -> get -> delete
    _ = cache.Set(c, "user:42:profile", Profile{Name: "Ada"}, time.Minute)
    profile, ok, err := cache.Get[Profile](c, "user:42:profile")
    fmt.Println(err == nil, ok, profile.Name) // true true Ada
    _ = c.Delete("user:42:profile")

    // String lifecycle: set -> get -> delete
    _ = c.SetString("settings:mode", "dark", time.Minute)
    mode, ok, err := c.GetString("settings:mode")
    fmt.Println(err == nil, ok, mode) // true true dark
    _ = c.Delete("settings:mode")

    // Remember pattern.
    profile, err := cache.Remember[Profile](c, "user:42:profile", time.Minute, func() (Profile, error) {
        return Profile{Name: "Ada"}, nil
    })
    fmt.Println(profile.Name) // Ada

    // Switch to Redis (dependency injection, no code changes below).
    store = rediscache.New(rediscache.Config{
        BaseConfig: cachecore.BaseConfig{
            Prefix:     "app",
            DefaultTTL: 5 * time.Minute,
        },
        Addr
View on GitHub
GitHub Stars5
CategoryData
Updated14d ago
Forks0

Languages

Go

Security Score

90/100

Audited on Mar 18, 2026

No findings