A universal cache facade library for Go, supporting both out-of-the-box usage and deep customization.
📘 中文文档请查看: README_zh.md
cachalot is a generic cache library based on Go generics. The core goal is to reduce the combinatorial complexity of m cache implementations with n cache usage patterns from O(m*n) to O(m+n).
It is not a specific cache system, but rather abstracts common caching patterns into reusable and composable capabilities.
This project is currently focused on gathering early feedback and is not production-ready yet. The API is not frozen, and APIs/default behaviors may still change before the first stable release. Feedback is highly welcome on:
- API naming and semantics.
- Usage ergonomics in real service flows.
- Default strategy implementations (fetch/write-back/singleflight).
- Extension experience for custom store/factory/decorator integrations.
Both cachalot and eko/gocache aim to simplify cache access, but they optimize for different things:
eko/gocachefocuses on a unified facade with ready-to-use adapters for fast adoption.cachalotfocuses on structured layering with explicitStore,Factory, andDecoratorboundaries.
This separation makes it easier to compose features by evolving storage implementation, construction/type-bridging logic, and usage policies independently.
- Single-level cache with pluggable
Storeimplementations. - Multi-level cache with customizable fetch and write-back policies.
- Decorator-based capability orchestration (codec, compression, logical expiry, singleflight, miss loader).
- Unified observability (metrics + logger).
- Both high-level Builder API (out-of-the-box usage) and low-level core API (fine-grained orchestration).
go get github.com/yikakia/cachalotbuilder, err := cachalot.NewBuilder[User]("user-cache", store)
if err != nil {
panic(err)
}
cache, err := builder.
WithCacheMissLoader(loadUser).
WithCacheMissDefaultWriteBackTTL(time.Minute).
Build()
if err != nil {
panic(err)
}
u, err := cache.Get(context.Background(), "user-1")For complete runnable examples, see examples:
- examples/01_basic
- examples/02_codec
- examples/03_logical_expiry
- examples/04_observability
- examples/05_advanced_multi_cache
- examples/06_remote_byte_path
Builder API(recommended for most scenarios): Out-of-the-box, with commonly-used features integrated by default.corepackage (advanced customization): Use when you need precise control over factories, decorator chains, and multi-level policies.
Common options:
WithCacheMissLoader: Load from origin when a key is missed.WithCacheMissDefaultWriteBackTTL: Default write-back TTL after loader returns successfully.WithSingleflight: Merge concurrent requests.WithCodec: Codec for byte-oriented stores.WithCompression: Byte-stage compression/decompression.WithLogicExpire*: Logical expiration (stale-while-revalidate).WithLogger/WithMetrics: Observability integration.
Common options:
WithLoader: Fallback loader when all levels miss (singleflight for the same key is enabled by default; disable viaWithSingleflight(false)).WithFetchPolicy: Customize probing order and load strategy across levels.WithWriteBack/WithWriteBackFilter: Control write-back behavior and target-level filtering rules.WithErrorHandling: Control strict/tolerant behavior for write-back failures.
For full control over the pipeline, use:
core/cache: Single-cache abstractions (Cache,Store, Option, Factory/Decorator).core/multicache: Multi-level cache orchestration (Config, policy functions, error handling).core/decorator: Reusable capability decorators.
The single-cache core architecture is divided into three layers:
Decorator: Defines "how to use cache" (concurrent deduplication, load-through, cache penetration protection, observability, etc.).Factory: AdaptsStoretoCache[T]and handles type bridging.Store: Encapsulates the concrete storage client and provides unified read/write semantics.
The default assembly order of Builder and the decorator execution model are described in:
- TODOs: TODO.md
- Architecture and decorator chain: docs/ARCHITECTURE.md
- FAQ: docs/FAQ.md
- Contributing Guide: docs/CONTRIBUTING.md
- Decision Matrix: docs/DECISION_MATRIX.md
This repo uses mockgen to generate interface mocks for unit tests:
internal/mocks/mock_cache.goforcache.Cache[T]internal/mocks/mock_store.goforcache.Store
Regenerate mocks with:
go generate ./internal/mocksRun tests:
go test ./...Or run the full script (including submodules):
./run_tests.sh© yikakia, 2026~time.Now()
Released under the MIT License.