{"id":23155925,"url":"https://github.com/hyp3rd/hypercache","last_synced_at":"2026-05-14T00:01:47.024Z","repository":{"id":65163585,"uuid":"583078224","full_name":"hyp3rd/hypercache","owner":"hyp3rd","description":"HyperCache is a thread-safe high-performance cache implementation in `Go` that supports multiple backends with optional size limits, item expiration, and pluggable eviction algorithms. It can be used as a standalone cache (single process or distributed via Redis / Redis Cluster) or wrapped by the to decorate operations with middleware","archived":false,"fork":false,"pushed_at":"2026-05-10T12:57:04.000Z","size":62038,"stargazers_count":5,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-05-10T14:35:36.703Z","etag":null,"topics":["cache","caching","distributed-cache","distributed-computing","go","golang","high-performance","redis-cache"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/hyp3rd.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":"CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":"ROADMAP.md","authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":["hyp3rd"]}},"created_at":"2022-12-28T17:43:01.000Z","updated_at":"2026-05-10T12:56:45.000Z","dependencies_parsed_at":"2025-12-27T19:04:52.485Z","dependency_job_id":null,"html_url":"https://github.com/hyp3rd/hypercache","commit_stats":{"total_commits":105,"total_committers":2,"mean_commits":52.5,"dds":0.01904761904761909,"last_synced_commit":"8e2eb45d9961742bf67700d26663893b97884600"},"previous_names":[],"tags_count":54,"template":false,"template_full_name":null,"purl":"pkg:github/hyp3rd/hypercache","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hyp3rd%2Fhypercache","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hyp3rd%2Fhypercache/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hyp3rd%2Fhypercache/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hyp3rd%2Fhypercache/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hyp3rd","download_url":"https://codeload.github.com/hyp3rd/hypercache/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hyp3rd%2Fhypercache/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33004768,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-13T13:14:54.681Z","status":"ssl_error","status_checked_at":"2026-05-13T13:14:51.610Z","response_time":115,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cache","caching","distributed-cache","distributed-computing","go","golang","high-performance","redis-cache"],"created_at":"2024-12-17T21:11:58.100Z","updated_at":"2026-05-14T00:01:46.982Z","avatar_url":"https://github.com/hyp3rd.png","language":"Go","funding_links":["https://github.com/sponsors/hyp3rd"],"categories":[],"sub_categories":[],"readme":"# HyperCache\n\n[![Go](https://github.com/hyp3rd/hypercache/actions/workflows/go.yml/badge.svg)][build-link] [![CodeQL](https://github.com/hyp3rd/hypercache/actions/workflows/codeql.yml/badge.svg)][codeql-link] [![Docs](https://img.shields.io/badge/docs-github--pages-blue)](https://hyp3rd.github.io/hypercache/)\n\n\u003e **📖 Full documentation**: \u003chttps://hyp3rd.github.io/hypercache/\u003e\n\n## Synopsis\n\nHyperCache is a **thread-safe** **high-performance** cache implementation in `Go` that supports multiple backends with optional size limits, item expiration, and pluggable eviction algorithms. It can be used as a standalone cache (single process or distributed via Redis / Redis Cluster) or wrapped by the [service interface](./service.go) to decorate operations with middleware (logging, metrics, tracing, etc.).\n\nIt is optimized for performance and flexibility:\n\n- Tunable expiration and eviction intervals (or fully proactive eviction when the eviction interval is set to `0`).\n- Debounced \u0026 coalesced expiration trigger channel to avoid thrashing.\n- Non-blocking manual `TriggerEviction(context.Context)` signal.\n- Serializer‑aware memory accounting (item size reflects the backend serialization format when available).\n- Multiple eviction algorithms with the ability to register custom ones.\n- Multiple stats collectors (default histogram) and middleware hooks.\n\nIt ships with a default [histogram stats collector](./stats/stats.go) and several eviction algorithms. You can register new ones by implementing the [Eviction Algorithm interface](./eviction/eviction.go):\n\n- [Recently Used (LRU) eviction algorithm](./eviction/lru.go)\n- [The Least Frequently Used (LFU) algorithm](./eviction/lfu.go)\n- [Cache-Aware Write-Optimized LFU (CAWOLFU)](./eviction/cawolfu.go)\n- [The Adaptive Replacement Cache (ARC) algorithm](./eviction/arc.go) — Experimental (not enabled by default)\n- [The clock eviction algorithm](./eviction/clock.go)\n\n### Features\n\n- Thread-safe \u0026 lock‑optimized (sharded map + worker pool)\n- High-performance (low allocations on hot paths, pooled items, serializer‑aware sizing)\n- Multiple backends (extensible): 1. [In-memory](./pkg/backend/inmemory.go) 1. [Redis](./pkg/backend/redis.go) 1. [Redis Cluster](./pkg/backend/redis_cluster.go)\n- Item expiration \u0026 proactive expiration triggering (debounced/coalesced)\n- Background or proactive (interval = 0) eviction using pluggable algorithms\n- Manual, non-blocking eviction triggering (`TriggerEviction()`)\n- Maximum cache size (bytes) \u0026 capacity (item count) controls\n- Serializer‑aware size accounting for consistent memory tracking across backends\n- Stats collection (histogram by default) + pluggable collectors\n- Middleware-friendly service wrapper (logging, metrics, tracing, custom)\n- Zero-cost if an interval is disabled (tickers are only created when \u003e 0)\n\n### Optional Management HTTP API\n\nYou can enable a lightweight management HTTP server to inspect and control a running cache instance.\n\nAdd the option when creating the config:\n\n```go\ncfg := hypercache.NewConfig[backend.InMemory](constants.InMemoryBackend)\ncfg.HyperCacheOptions = append(cfg.HyperCacheOptions,\n    hypercache.WithManagementHTTP[backend.InMemory](\"127.0.0.1:9090\"),\n)\nhc, _ := hypercache.New(context.Background(), hypercache.GetDefaultManager(), cfg)\n```\n\nEndpoints (subject to change):\n\n- GET /health – liveness check\n- GET /stats – current stats snapshot\n- GET /config – sanitized runtime config (now includes replication + virtual node settings when using DistMemory)\n- GET /dist/metrics – distributed backend forwarding / replication counters (DistMemory only)\n- GET /dist/owners?key=K – current ring owners (IDs) for key K (DistMemory only, debug)\n- GET /internal/merkle – Merkle tree snapshot (DistMemory experimental anti-entropy)\n- GET /internal/keys – Full key enumeration (debug / anti-entropy fallback; expensive)\n- GET /cluster/members – membership snapshot (id, address, state, incarnation, replication factor, virtual nodes)\n- GET /cluster/ring – ring vnode hashes (debug / diagnostics)\n- POST /evict – trigger eviction cycle\n- POST /trigger-expiration – trigger expiration scan\n- POST /clear – clear all items\n\nBind to 127.0.0.1 by default and wrap with an auth function via `WithMgmtAuth` for production use.\n\n## Installation\n\nInstall HyperCache:\n\n```bash\ngo get -u github.com/hyp3rd/hypercache\n```\n\n### Performance\n\nSample benchmark output (numbers will vary by hardware / Go version):\n\n```bash\ngoos: darwin\ngoarch: arm64\npkg: github.com/hyp3rd/hypercache/tests/benchmark\ncpu: Apple M2 Pro\nBenchmarkHyperCache_Get-12                        72005894          66.71 ns/op         0 B/op           0 allocs/op\nBenchmarkHyperCache_Get_ProactiveEviction-12      71068249          67.22 ns/op         0 B/op           0 allocs/op\nBenchmarkHyperCache_List-12                       36435114          129.5 ns/op        80 B/op           1 allocs/op\nBenchmarkHyperCache_Set-12                        10365289          587.4 ns/op       191 B/op           3 allocs/op\nBenchmarkHyperCache_Set_Proactive_Eviction-12      3264818           1521 ns/op       282 B/op           5 allocs/op\nPASS\nok   github.com/hyp3rd/hypercache/tests/benchmark 26.853s\n```\n\n### Examples\n\nTo run the examples, use the following command:\n\n```bash\nmake run-example group=eviction  # or any other example\n```\n\nFor a complete list of examples, refer to the [examples](./examples/README.md) directory.\n\n### Observability (OpenTelemetry)\n\nHyperCache provides optional OpenTelemetry middleware for tracing and metrics.\n\n- Tracing: wrap the service with `middleware.NewOTelTracingMiddleware` using a `trace.Tracer`.\n- Metrics: wrap with `middleware.NewOTelMetricsMiddleware` using a `metric.Meter`.\n\nExample wiring:\n\n```go\nsvc := hypercache.ApplyMiddleware(svc,\n    func(next hypercache.Service) hypercache.Service { return middleware.NewOTelTracingMiddleware(next, tracer) },\n    func(next hypercache.Service) hypercache.Service { mw, _ := middleware.NewOTelMetricsMiddleware(next, meter); return mw },\n)\n```\n\nUse your preferred OpenTelemetry SDK setup for exporters and processors in production; the snippet uses no-op providers for simplicity.\n\n### Eviction algorithms\n\nAvailable algorithm names you can pass to `WithEvictionAlgorithm`:\n\n- \"lru\" — Least Recently Used (default)\n- \"lfu\" — Least Frequently Used (with LRU tie-breaker for equal frequencies)\n- \"clock\" — Second-chance clock\n- \"cawolfu\" — Cache-Aware Write-Optimized LFU\n- \"arc\" — Adaptive Replacement Cache (experimental; not registered by default)\n\nNote: ARC is experimental and isn’t included in the default registry. If you choose to use it, register it manually or enable it explicitly in your build.\n\n#### Sharded eviction (default since v0.5.0)\n\nThe configured algorithm is wrapped by a 32-shard router (`pkg/eviction/sharded.go`) that uses the same key hash as `ConcurrentMap` — so a key's data shard and eviction shard line up. This eliminates the global mutex contention single-instance algorithms (LRU/LFU/Clock/CAWOLFU) suffer from. Total capacity is honored within ±32 (one slot of slack per shard), and items evict per-shard rather than in strict global LRU/LFU order.\n\nUse `WithEvictionShardCount(1)` to disable sharding when you need strict-global ordering at the cost of single-mutex contention. Pass any other positive power of two to tune (e.g. `WithEvictionShardCount(64)`).\n\n## API\n\n`NewInMemoryWithDefaults(ctx, capacity)` is the quickest way to start:\n\n```golang\ncache, err := hypercache.NewInMemoryWithDefaults(context.Background(), 100)\nif err != nil {\n    // handle error\n}\n```\n\nFor fine‑grained control use `NewConfig` + `New`:\n\n```golang\nconfig := hypercache.NewConfig[backend.InMemory](constants.InMemoryBackend)\nconfig.HyperCacheOptions = []hypercache.Option[backend.InMemory]{\n    hypercache.WithEvictionInterval[backend.InMemory](time.Minute * 5),\n    hypercache.WithEvictionAlgorithm[backend.InMemory](\"cawolfu\"),\n    hypercache.WithExpirationTriggerDebounce[backend.InMemory](250 * time.Millisecond),\n    hypercache.WithMaxEvictionCount[backend.InMemory](100),\n    hypercache.WithMaxCacheSize[backend.InMemory](64 * 1024 * 1024), // 64 MiB logical cap\n}\nconfig.InMemoryOptions = []backend.Option[backend.InMemory]{ backend.WithCapacity[backend.InMemory](10) }\n\ncache, err := hypercache.New(context.Background(), hypercache.GetDefaultManager(), config)\nif err != nil {\n    fmt.Fprintln(os.Stderr, err)\n    return\n}\n```\n\n### Advanced options quick reference\n\n| Option                          | Purpose                                                                                           |\n| ------------------------------- | ------------------------------------------------------------------------------------------------- |\n| `WithEvictionInterval`          | Periodic eviction loop; set to `0` for proactive per-write eviction.                              |\n| `WithExpirationInterval`        | Periodic scan for expired items.                                                                  |\n| `WithExpirationTriggerBuffer`   | Buffer size for coalesced expiration trigger channel.                                             |\n| `WithExpirationTriggerDebounce` | Drop rapid-fire triggers within a window.                                                         |\n| `WithEvictionAlgorithm`         | Select eviction algorithm (lru, lfu, clock, cawolfu, arc\\*).                                      |\n| `WithEvictionShardCount`        | Number of eviction-algorithm shards (default 32; 1 disables sharding).                            |\n| `WithMaxEvictionCount`          | Cap number of items evicted per cycle.                                                            |\n| `WithMaxCacheSize`              | Max cumulative serialized item size (bytes).                                                      |\n| `WithStatsCollector`            | Choose stats collector implementation.                                                            |\n| `WithManagementHTTP`            | Start optional management HTTP server.                                                            |\n| `WithDistReplication`           | (DistMemory) Set replication factor (owners per key).                                             |\n| `WithDistVirtualNodes`          | (DistMemory) Virtual nodes per physical node for consistent hashing.                              |\n| `WithDistMerkleChunkSize`       | (DistMemory) Keys per Merkle leaf chunk (power-of-two recommended).                               |\n| `WithDistMerkleAutoSync`        | (DistMemory) Interval for background Merkle sync (\u003c=0 disables).                                  |\n| `WithDistMerkleAutoSyncPeers`   | (DistMemory) Limit peers synced per auto-sync tick (0=all).                                       |\n| `WithDistListKeysCap`           | (DistMemory) Cap number of keys fetched via fallback enumeration.                                 |\n| `WithDistNode`                  | (DistMemory) Explicit node identity (id/address).                                                 |\n| `WithDistSeeds`                 | (DistMemory) Static seed addresses to pre-populate membership.                                    |\n| `WithDistTombstoneTTL`          | (DistMemory) Retain delete tombstones for this duration before compaction (\u003c=0 = infinite).       |\n| `WithDistTombstoneSweep`        | (DistMemory) Interval to run tombstone compaction (\u003c=0 disables).                                 |\n| `WithDistHTTPLimits`            | (DistMemory) Body / response / timeout / concurrency caps for the dist HTTP server + auto-client. |\n| `WithDistHTTPAuth`              | (DistMemory) Bearer-token auth (`Token`) plus optional `ServerVerify` / `ClientSign` hooks.       |\n\n\\*ARC is experimental (not registered by default).\n\n### Type-safe access (`Typed[V]`)\n\nThe untyped `HyperCache.Get` returns `(any, bool)`, so callers must\ntype-assert at every call site. `hypercache.NewTyped[T, V]` wraps an\nexisting `*HyperCache[T]` to provide a compile-time-typed surface\nwithout changing the underlying storage:\n\n```go\nhc, _ := hypercache.NewInMemoryWithDefaults(ctx, 10_000)\nsessions := hypercache.NewTyped[backend.InMemory, *Session](hc)\n\n_ = sessions.Set(ctx, \"u:42\", \u0026Session{UserID: \"u-42\"}, time.Hour)\ns, ok := sessions.Get(ctx, \"u:42\") // s is *Session — no type assert\n```\n\nMultiple `Typed[V1]`, `Typed[V2]` views can share one underlying\ncache over disjoint keyspaces. Wrong-type reads return `(zero, false)`\nby default (fail-soft); use `GetTyped` for an explicit\n`sentinel.ErrTypeMismatch`. See\n[docs/rfcs/0002-generic-item-typing.md](docs/rfcs/0002-generic-item-typing.md)\nfor the design and the v3 deep-generics roadmap.\n\n### Redis / Redis Cluster notes\n\nWhen using Redis or Redis Cluster, item size accounting uses the configured serializer (e.g. msgpack) to align in-memory and remote representations. Provide the serializer via backend options (`WithSerializer` / `WithClusterSerializer`).\n\n**Refer to [config.go](./config.go) for complete option definitions and the GoDoc on pkg.go.dev for an exhaustive API reference.**\n\n## Usage\n\n### Distributed In‑Process Backend (Experimental)\n\nThe experimental in‑process distributed backend `DistMemory` (feature branch: `feat/distributed-backend`) simulates a small cluster inside a single process using a consistent hash ring with virtual nodes, replication, quorum consistency, forwarding, replica fan‑out, rebalancing, hinted handoff, tombstones and Merkle-based anti‑entropy.\n\nA detailed deep dive lives in [docs/distributed.md](./docs/distributed.md). Below is a concise summary.\n\nCurrent capabilities (implemented):\n\n- Static membership + ring with configurable replication factor \u0026 virtual nodes.\n- Ownership enforcement (non‑owners forward to primary; promotion if primary unreachable).\n- Replica fan‑out on writes + replica removals.\n- Quorum reads \u0026 writes (ONE / QUORUM / ALL) with read repair.\n- Hinted handoff (TTL, replay, per-node + global caps, metrics).\n- Delete semantics with versioned tombstones (TTL + compaction, anti‑resurrection guard).\n- Merkle tree anti‑entropy (build/diff/pull) + metrics.\n- Periodic auto Merkle sync (peer cap optional).\n- Heartbeat-based failure detection (alive→suspect→dead) + metrics.\n- Lightweight gossip snapshot exchange (in-process only).\n- Rebalancing (primary change \u0026 lost ownership migrations) with batching and concurrency throttling metrics.\n- Latency histograms for Get/Set/Remove.\n- HTTP transport hardening: bounded request/response bodies, idle-connection timeout, concurrency cap, bearer-token auth, TLS / mTLS via `*tls.Config`, lifecycle-context cancellation on `Stop`, and surfaced listener errors. See \"Transport hardening\" below.\n\nLimitations / not yet implemented:\n\n- Full gossip-based dynamic membership \u0026 indirect probing.\n- Advanced versioning (HLC / vector clocks).\n- Tracing spans for distributed operations.\n- Compression on the wire.\n- Persistence / durability (out of scope presently).\n\n#### Transport hardening (since v0.5.0)\n\nThe dist HTTP server and the auto-created HTTP client share a single configuration surface — apply the same option to every node in the cluster.\n\n```go\n// 1) Limits: body caps, timeouts, concurrency, optional TLS.\nlimits := backend.DistHTTPLimits{\n    BodyLimit:     16 * 1024 * 1024, // server inbound cap\n    ResponseLimit: 16 * 1024 * 1024, // client inbound cap\n    IdleTimeout:   60 * time.Second,\n    TLSConfig:     tlsConfig,        // non-nil enables HTTPS on both sides\n}\n\n// 2) Auth: a shared bearer token covers most clusters; ServerVerify /\n//    ClientSign hooks are escape hatches for JWT, mTLS-derived\n//    identity, HMAC, etc. The hypercache-server binary uses the\n//    ServerVerify hook to plug in an OIDC verifier\n//    (cmd/hypercache-server/oidc.go) when HYPERCACHE_OIDC_ISSUER is\n//    set; static-bearer logins coexist with IdP-issued JWTs.\nauth := backend.DistHTTPAuth{Token: \"shared-cluster-secret\"}\n\nbi, _ := backend.NewDistMemory(ctx,\n    backend.WithDistNode(\"nodeA\", \"127.0.0.1:7001\"),\n    backend.WithDistReplication(3),\n    backend.WithDistHTTPLimits(limits),\n    backend.WithDistHTTPAuth(auth),\n)\n```\n\nOperational helpers:\n\n- `DistMemory.LifecycleContext()` — context derived from the constructor's; canceled on `Stop()`. In-flight handlers and replica forwards observe `Done()`.\n- `LastServeError()` on both `distHTTPServer` and `ManagementHTTPServer` — replaces the prior silent-swallow of listener-loop crashes.\n\nDefaults if `WithDistHTTPLimits` is not supplied: 16 MiB body cap, 5 s read/write/client timeouts, 60 s idle, fiber's 256 KiB concurrency cap. Auth is disabled by default.\n\n#### Rebalancing \u0026 Ownership Migration (Experimental Phase 3)\n\nThe DistMemory backend includes an experimental periodic rebalancer that:\n\n- Scans local shards each tick (interval configurable via `WithDistRebalanceInterval`).\n- Collects candidate keys when this node either (a) is no longer an owner (primary or replica) or (b) was the recorded primary and the current primary changed.\n- Migrates candidates in batches (`WithDistRebalanceBatchSize`) with bounded parallelism (`WithDistRebalanceMaxConcurrent`).\n- Uses a semaphore; saturation increments the `RebalanceThrottle` metric.\n\nMigration is best‑effort (fire‑and‑forget forward of the item to the new primary); failures are not yet retried or queued. Owner set diffing now covers:\n\n- Primary change \u0026 full ownership loss (migrate off this node).\n- Replica-only additions (push current value to newly added replicas; capped by `WithDistReplicaDiffMaxPerTick`).\n\nReplica removal cleanup (actively dropping data from nodes no longer replicas) is pending.\n\nMetrics (via management or `Metrics()`):\n\n| Metric                       | Description                                                                              |\n| ---------------------------- | ---------------------------------------------------------------------------------------- |\n| RebalancedKeys               | Count of all rebalance-related migrations (primary changes + replica diff replications). |\n| RebalancedPrimary            | Count of primary ownership change migrations (subset of RebalancedKeys).                 |\n| RebalanceBatches             | Number of migration batches executed.                                                    |\n| RebalanceThrottle            | Times migration concurrency limiter saturated.                                           |\n| RebalanceLastNanos           | Duration (ns) of last rebalance scan.                                                    |\n| RebalancedReplicaDiff        | Count of replica-only diff replications (new replicas seeded).                           |\n| RebalanceReplicaDiffThrottle | Times replica-only diff processing hit per-tick cap.                                     |\n\nTest helpers `AddPeer` and `RemovePeer` simulate join / leave events that trigger redistribution in integration tests (`dist_rebalance_*.go`).\n\n### Roadmap / PRD Progress Snapshot\n\n| Area                                                               | Status                                                    |\n| ------------------------------------------------------------------ | --------------------------------------------------------- |\n| Core in-process sharding                                           | Done                                                      |\n| Replication fan-out                                                | Done                                                      |\n| Read-repair                                                        | Done                                                      |\n| Quorum consistency (R/W)                                           | Done                                                      |\n| Hinted handoff (TTL, replay, caps)                                 | Done                                                      |\n| Tombstones (TTL + compaction)                                      | Done                                                      |\n| Merkle anti-entropy (pull)                                         | Done                                                      |\n| Merkle phase metrics                                               | Done                                                      |\n| Auto Merkle background sync                                        | Done                                                      |\n| Rebalancing (primary/lost ownership + replica-add diff + shedding) | Partial (shedding grace delete added; future retry/queue) |\n| Failure detection (heartbeat)                                      | Partial (basic)                                           |\n| Lightweight gossip snapshot                                        | Partial                                                   |\n| Replica-only migration diff                                        | Planned                                                   |\n| Adaptive Merkle scheduling                                         | Planned                                                   |\n| Advanced versioning (HLC/vector)                                   | Planned                                                   |\n| Client SDK (direct routing)                                        | Planned                                                   |\n| Tracing spans                                                      | Planned                                                   |\n| Security (TLS/auth)                                                | Done (since v0.5.0; see \"Transport hardening\")            |\n| Compression                                                        | Planned                                                   |\n| Persistence                                                        | Out of scope (current phase)                              |\n| Chaos / fault injection                                            | Planned                                                   |\n| Benchmarks \u0026 tests                                                 | Ongoing (broad coverage)                                  |\n\nExample minimal setup:\n\n```go\ncfg := hypercache.NewConfig[backend.DistMemory](constants.DistMemoryBackend)\ncfg.HyperCacheOptions = append(cfg.HyperCacheOptions,\n    hypercache.WithManagementHTTP[backend.DistMemory](\"127.0.0.1:9090\"),\n)\ncfg.DistMemoryOptions = []backend.Option[backend.DistMemory]{\n    backend.WithDistReplication(3),\n    backend.WithDistVirtualNodes(64),\n    backend.WithDistNode(\"node-a\", \"127.0.0.1:7000\"),\n    backend.WithDistSeeds([]string{\"127.0.0.1:7001\", \"127.0.0.1:7002\"}),\n}\nhc, err := hypercache.New(context.Background(), hypercache.GetDefaultManager(), cfg)\nif err != nil { log.Fatal(err) }\ndefer hc.Stop(context.Background())\n```\n\nNote: DistMemory is not a production distributed cache; it is a stepping stone towards a networked, failure‑aware implementation.\n\n#### Consistency \u0026 Quorum Semantics\n\nDistMemory currently supports three consistency levels configurable independently for reads and writes:\n\n- ONE: Return after the primary (or first reachable owner) succeeds.\n- QUORUM: Majority of owners (floor(R/2)+1) must acknowledge.\n- ALL: Every owner must acknowledge; any unreachable replica causes failure.\n\nRequired acknowledgements are computed at runtime from the ring's current replication factor. For writes, the primary applies locally then synchronously fans out to remaining owners; for reads, it queries owners until the required number of successful responses is achieved (promoting next owner if a primary is unreachable). Read‑repair occurs when a later owner returns a newer version than the local primary copy.\n\n#### Hinted Handoff\n\nWhen a replica is unreachable during a write, a hint (deferred write) is enqueued locally keyed by the target node ID. Hints have a TTL (`WithDistHintTTL`) and are replayed on an interval (`WithDistHintReplayInterval`). Limits can be applied per node (`WithDistHintMaxPerNode`) as well as globally across all nodes (`WithDistHintMaxTotal` total entries, `WithDistHintMaxBytes` approximate bytes). Expired hints are dropped; delivered hints increment replay counters; globally capped drops increment a separate metric. Metrics exposed via the management endpoint allow monitoring queued, replayed, expired, dropped (transport errors), and globally dropped hints along with current approximate queued bytes.\n\nTest helper methods for forcing a replay cycle (`StartHintReplayForTest`, `ReplayHintsForTest`, `HintedQueueSize`) are compiled only under the `test` build tag to keep production binaries clean.\n\nTo run tests that rely on these helpers:\n\n```bash\ngo test -tags test ./...\n```\n\n#### Build Tags\n\nThe repository uses a `//go:build test` tag to include auxiliary instrumentation and helpers exclusively in test builds (e.g. hinted handoff queue inspection). Production builds omit these symbols automatically. Heartbeat peer sampling (`WithDistHeartbeatSample`) and membership state metrics (suspect/dead counters) are part of the experimental failure detection added in Phase 2.\n\n#### Metrics Snapshot\n\nThe `/dist/metrics` endpoint (and `DistMemory.Metrics()` API) expose counters for forwarding operations, replica fan‑out, read‑repair, hinted handoff lifecycle, quorum write attempts/acks/failures, Merkle sync timings, tombstone activity, and heartbeat probes. These are reset only on process restart.\n\n#### Future Evolution (Selected)\n\nPrioritized next steps (see `docs/distributed.md` for full context):\n\n- Replica-only ownership diff \u0026 migration (push of newly added replicas implemented; removal/cleanup pending).\n- Migration retry queue \u0026 success/failure metrics.\n- Adaptive / incremental Merkle scheduling.\n- Client SDK with direct owner hashing.\n- Tracing spans for distributed ops (Set, Get, Repair, Merkle, Rebalance, HintReplay).\n- Enhanced failure detection (indirect probes, gossip dissemination).\n- Security (TLS/mTLS) + auth middleware.\n- Chaos \u0026 latency / fault injection hooks.\n\nDistMemory remains experimental; treat interfaces as unstable until promoted out of the feature branch.\n\nExamples can be too broad for a readme, refer to the [examples](./__examples/README.md) directory for a more comprehensive overview.\n\n## License\n\nThe code and documentation in this project are released under Mozilla Public License 2.0.\n\n## Author\n\nI'm a surfer, and a software architect with 15 years of experience designing highly available distributed production systems and developing cloud-native apps in public and private clouds. Feel free to connect with me on LinkedIn.\n\n[![LinkedIn](https://img.shields.io/badge/LinkedIn-0077B5?style=for-the-badge\u0026logo=linkedin\u0026logoColor=white)](https://www.linkedin.com/in/francesco-cosentino/)\n\n[build-link]: https://github.com/hyp3rd/hypercache/actions/workflows/go.yml\n[codeql-link]: https://github.com/hyp3rd/hypercache/actions/workflows/codeql.yml\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhyp3rd%2Fhypercache","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhyp3rd%2Fhypercache","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhyp3rd%2Fhypercache/lists"}