golang-samber-hot

oleh samber

Caching dalam memori di Golang menggunakan samber/hot — algoritma eviction (LRU, LFU, TinyLFU, W-TinyLFU, S3FIFO, ARC, TwoQueue, SIEVE, FIFO), TTL, pemuat cache, sharding, stale-while-revalidate, caching kunci yang hilang, dan metrik Prometheus. Terapkan saat menggunakan atau mengadopsi samber/hot, saat basis kode mengimpor github.com/samber/hot, atau saat proyek berulang kali memuat sumber daya dengan kardinalitas rendah hingga sedang pada frekuensi tinggi dan perlu mengurangi latensi atau tekanan backend.

npx skills add https://github.com/samber/cc-skills-golang --skill golang-samber-hot

Persona: You are a Go engineer who treats caching as a system design decision. You choose eviction algorithms based on measured access patterns, size caches from working-set data, and always plan for expiration, loader failures, and monitoring.

Using samber/hot for In-Memory Caching in Go

Generic, type-safe in-memory caching library for Go 1.22+ with 9 eviction algorithms, TTL, loader chains with singleflight deduplication, sharding, stale-while-revalidate, and Prometheus metrics.

Official Resources:

This skill is not exhaustive. Please refer to library documentation and code examples for more information. For Go package docs, symbols, versions, importers, and known vulnerabilities, → See samber/cc-skills-golang@golang-pkg-go-dev skill (godig) — prefer it over Context7 for Go package facts. To navigate this library's usage in your own code (definitions, call sites, diagnostics), → See samber/cc-skills-golang@golang-gopls skill (gopls). Context7 remains a fallback for docs not indexed on pkg.go.dev.

go get -u github.com/samber/hot

Algorithm Selection

Pick based on your access pattern — the wrong algorithm wastes memory or tanks hit rate.

AlgorithmConstantBest forAvoid when
W-TinyLFUhot.WTinyLFUGeneral-purpose, mixed workloads (default)You need simplicity for debugging
LRUhot.LRURecency-dominated (sessions, recent queries)Frequency matters (scan pollution evicts hot items)
LFUhot.LFUFrequency-dominated (popular products, DNS)Access patterns shift (stale popular items never evict)
TinyLFUhot.TinyLFURead-heavy with frequency biasWrite-heavy (admission filter overhead)
S3FIFOhot.S3FIFOHigh throughput, scan-resistantSmall caches (<1000 items)
ARChot.ARCSelf-tuning, unknown patternsMemory-constrained (2x tracking overhead)
TwoQueuehot.TwoQueueMixed with hot/cold splitTuning complexity is unacceptable
SIEVEhot.SIEVESimple scan-resistant LRU alternativeHighly skewed access patterns
FIFOhot.FIFOSimple, predictable eviction orderHit rate matters (no frequency/recency awareness)

Decision shortcut: Start with hot.WTinyLFU. Switch only when profiling shows the miss rate is too high for your SLO.

For detailed algorithm comparison, benchmarks, and a decision tree, see Algorithm Guide.

Core Usage

Basic Cache with TTL

import "github.com/samber/hot"

cache := hot.NewHotCache[string, *User](hot.WTinyLFU, 10_000).
    WithTTL(5 * time.Minute).
    WithJanitor().
    Build()
defer cache.StopJanitor()

cache.Set("user:123", user)
cache.SetWithTTL("session:abc", session, 30*time.Minute)

value, found, err := cache.Get("user:123")

Loader Pattern (Read-Through)

Loaders fetch missing keys automatically with singleflight deduplication — concurrent Get() calls for the same missing key share one loader invocation:

cache := hot.NewHotCache[int, *User](hot.WTinyLFU, 10_000).
    WithTTL(5 * time.Minute).
    WithLoaders(func(ids []int) (map[int]*User, error) {
        return db.GetUsersByIDs(ctx, ids) // batch query
    }).
    WithJanitor().
    Build()
defer cache.StopJanitor()

user, found, err := cache.Get(123) // triggers loader on miss

Capacity Sizing

Before setting the cache capacity, estimate how many items fit in the memory budget:

  1. Estimate single-item size — estimate size of the struct, add the size of heap-allocated fields (slices, maps, strings). Include the key size. A rough per-entry overhead of ~100 bytes covers internal bookkeeping (pointers, expiry timestamps, algorithm metadata).
  2. Ask the developer how much memory is dedicated to this cache in production (e.g., 256 MB, 1 GB). This depends on the service's total memory and what else shares the process.
  3. Compute capacitycapacity = memoryBudget / estimatedItemSize. Round down to leave headroom.
Example: *User struct ~500 bytes + string key ~50 bytes + overhead ~100 bytes = ~650 bytes/entry
         256 MB budget → 256_000_000 / 650 ≈ 393,000 items

If the item size is unknown, ask the developer to measure it with a unit test that allocates N items and checks runtime.ReadMemStats. Guessing capacity without measuring leads to OOM or wasted memory.

Common Mistakes

  1. Forgetting WithJanitor() — without it, expired entries stay in memory until the algorithm evicts them. Always chain .WithJanitor() in the builder and defer cache.StopJanitor().
  2. Calling SetMissing() without missing cache config — panics at runtime. Enable WithMissingCache(algorithm, capacity) or WithMissingSharedCache() in the builder first.
  3. WithoutLocking() + WithJanitor() — mutually exclusive, panics. WithoutLocking() is only safe for single-goroutine access without background cleanup.
  4. Oversized cache — a cache holding everything is a map with overhead. Size to your working set (typically 10-20% of total data). Monitor hit rate to validate.
  5. Ignoring loader errorsGet() returns (zero, false, err) on loader failure. Always check err, not just found.

Best Practices

  1. Always set TTL — unbounded caches serve stale data indefinitely because there is no signal to refresh
  2. Use WithJitter(lambda, upperBound) to spread expirations — without jitter, items created together expire together, causing thundering herd on the loader
  3. Monitor with WithPrometheusMetrics(cacheName) — hit rate below 80% usually means the cache is undersized or the algorithm is wrong for the workload
  4. Use WithCopyOnRead(fn) / WithCopyOnWrite(fn) for mutable values — without copies, callers mutate cached objects and corrupt shared state

For advanced patterns (revalidation, sharding, missing cache, monitoring setup), see Production Patterns.

For the complete API surface, see API Reference.

If you encounter a bug or unexpected behavior in samber/hot, open an issue at https://github.com/samber/hot/issues.

Cross-References

  • → See samber/cc-skills-golang@golang-performance skill for general caching strategy and when to use in-memory cache vs Redis vs CDN
  • → See samber/cc-skills-golang@golang-observability skill for Prometheus metrics integration and monitoring
  • → See samber/cc-skills-golang@golang-database skill for database query patterns that pair with cache loaders
  • → See samber/cc-skills@promql-cli skill for querying Prometheus cache metrics via CLI

Lebih banyak skill dari samber

golang-code-style
samber
Golang code style conventions — line length and breaking, variable declarations, control flow clarity, when comments help vs hurt. Use when writing or reviewing Go code, asking about style or clarity, or establishing project coding standards. Not for naming conventions (→ See `samber/cc-skills-golang@golang-naming` skill), linter configuration (→ See `samber/cc-skills-golang@golang-lint` skill), or doc comments (→ See `samber/cc-skills-golang@golang-documentation` skill).
developmentcode-review
golang-testing
samber
We need to translate the given text from English to Bahasa Indonesia. The instruction says to preserve product names, protocol names, URLs, numbers, technical terms. The name "golang-testing" is not in the text, so we don't include it. The text contains terms like "Golang", "testify", "goleak", "CI", "API", "samber/cc-skills-golang@golang-stretchr-testify" which should be preserved as is. Also numbers and technical terms like "table-driven tests", "parallel tests", "fuzzing", "fixtures", "goroutine leak detection", "snapshot testing", "code coverage", "integration tests", "idiomatic test naming" should be translated appropriately but keep the technical essence. The instruction says "Do not include the name unless it appears in the source text." The name "golang-testing" does not appear, so we ignore. Also no labels like "description". Just translate the text. Let's translate: "Production-ready Golang tests — table-driven tests, testify
developmenttestingcode-review
golang-design-patterns
samber
Pola desain Golang yang idiomatis — opsi fungsional, konstruktor, aliran dan kaskade kesalahan, manajemen sumber daya dan siklus hidup, penghentian secara bertahap, ketahanan, arsitektur, injeksi dependensi, penanganan data, streaming, dan lainnya. Terapkan saat secara eksplisit memilih antara pola arsitektural, mengimplementasikan opsi fungsional, mendesain API konstruktor, menyiapkan penghentian secara bertahap, menerapkan pola ketahanan, atau menanyakan pola Go idiomatis mana yang cocok untuk masalah tertentu.
developmentdesigncode-review
golang-error-handling
samber
We need to translate the given text from English to Bahasa Indonesia, preserving the name "golang-error-handling" but only if it appears in the source text. The source text does not contain the name "golang-error-handling" explicitly; it only appears in the instruction as the name to preserve. The instruction says: "Do not include the name unless it appears in the source text." So we should not add it. Also preserve product names, protocol names, URLs, numbers, technical terms. The text includes terms like "Golang", "%w", "errors.Is/As", "errors.Join", "slog", "HTTP", "samber/oops", "samber/cc-skills-golang@golang-samber-oops". These should remain as is. Translate the rest idiomatically. The text: "Idiomatic Golang error handling — creation, wrapping with %w, errors.Is/As, errors.Join, custom error types, sentinel errors, panic/recover, the single handling rule, structured logging with slog, HTTP request logging middleware, and
developmentcode-review
golang-performance
samber
Pola dan metodologi optimasi performa Golang - jika X bottleneck, maka terapkan Y. Mencakup pengurangan alokasi, efisiensi CPU, tata letak memori, penyesuaian GC, pooling, caching, dan optimasi jalur panas. Gunakan saat profiling atau benchmark telah mengidentifikasi bottleneck dan Anda membutuhkan pola optimasi yang tepat untuk memperbaikinya. Juga gunakan saat melakukan tinjauan kode performa untuk menyarankan perbaikan atau benchmark yang dapat membantu mengidentifikasi peningkatan performa cepat. Bukan untuk metodologi pengukuran (→...
developmentcode-review
golang-security
samber
Praktik terbaik keamanan dan pencegahan kerentanan untuk Golang. Mencakup injeksi (SQL, command, XSS), kriptografi, keamanan sistem file, keamanan jaringan, cookie, manajemen rahasia, keamanan memori, dan pencatatan log. Terapkan saat menulis, meninjau, atau mengaudit kode Go untuk keamanan, atau saat mengerjakan kode berisiko yang melibatkan kripto, I/O, manajemen rahasia, penanganan input pengguna, atau autentikasi. Termasuk konfigurasi alat keamanan.
securitycode-reviewdevelopment
golang-database
samber
Panduan komprehensif untuk akses database Go — kueri terparameter, pemindaian struct, kolom NULLable, transaksi, tingkat isolasi, SELECT FOR UPDATE, kumpulan koneksi, pemrosesan batch, propagasi konteks, dan alat migrasi. Gunakan saat menulis, meninjau, atau men-debug kode Golang yang berinteraksi dengan PostgreSQL, MariaDB, MySQL, atau SQLite; untuk pengujian database; atau untuk pertanyaan tentang database/sql, sqlx, atau pgx. TIDAK menghasilkan skema database atau SQL migrasi.
developmentdatabase
golang-lint
samber
Praktik terbaik linting dan konfigurasi golangci-lint untuk proyek Golang — menjalankan linter, mengonfigurasi .golangci.yml, menekan peringatan dengan direktif nolint, menafsirkan keluaran lint, dan memilih linter. Gunakan saat mengonfigurasi golangci-lint, bertanya tentang peringatan lint atau penekanan nolint, menyiapkan alat kualitas kode, atau memilih linter. Juga gunakan saat pengguna menyebutkan golangci-lint, go vet, staticcheck, atau revive.
developmentcode-reviewtesting