{"id":51080465,"url":"https://github.com/elares/ironcache","last_synced_at":"2026-06-30T02:01:45.301Z","repository":{"id":364605023,"uuid":"1268255754","full_name":"ELares/IronCache","owner":"ELares","description":"IronCache: a Rust, single-binary, Redis-compatible cache engineered to be the world's most efficient. Multi-core, memory-frugal, AI-driven, single node to multi-node.","archived":false,"fork":false,"pushed_at":"2026-06-23T05:03:39.000Z","size":6768,"stargazers_count":0,"open_issues_count":24,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-23T17:37:00.045Z","etag":null,"topics":["cache","caching","in-memory-database","key-value-store","redis","redis-alternative","redis-compatible","resp","rust","thread-per-core"],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ELares.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE-APACHE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":"SECURITY.md","support":null,"governance":"GOVERNANCE.md","roadmap":"docs/ROADMAP.md","authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-13T10:12:43.000Z","updated_at":"2026-06-23T04:59:05.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/ELares/IronCache","commit_stats":null,"previous_names":["elares/ironcache"],"tags_count":116,"template":false,"template_full_name":null,"purl":"pkg:github/ELares/IronCache","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ELares%2FIronCache","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ELares%2FIronCache/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ELares%2FIronCache/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ELares%2FIronCache/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ELares","download_url":"https://codeload.github.com/ELares/IronCache/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ELares%2FIronCache/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34949234,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-30T02:00:05.919Z","response_time":92,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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","in-memory-database","key-value-store","redis","redis-alternative","redis-compatible","resp","rust","thread-per-core"],"created_at":"2026-06-23T17:30:24.292Z","updated_at":"2026-06-30T02:01:45.295Z","avatar_url":"https://github.com/ELares.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"docs/assets/ironcache-logo.png\" alt=\"IronCache\" width=\"320\"\u003e\n\u003c/p\u003e\n\n# IronCache\n\n**A Redis-compatible cache in one static Rust binary: thread-per-core, replicated, clustered.**\n\nIronCache speaks the Redis wire protocol (RESP2 and RESP3) and keeps the observable\nRedis contract for the commands it implements, so existing Redis clients, libraries,\nand `redis-cli` work against it unchanged. It is a shared-nothing, thread-per-core\nengine: the keyspace is sharded so each shard is owned and mutated by exactly one\ncore, with no hot-path locks. It ships as a single static binary that is both the\nserver and the CLI.\n\nThe engine is functional and broad: 176 client-facing commands across all the core\ndata types, transactions, pub/sub with keyspace notifications, blocking commands,\non-disk persistence, and an opt-in Raft-governed multi-node cluster with replication,\nautomatic failover, and online slot migration. It is exercised by 1,500+ in-tree\ntests, a differential harness that proves byte-for-byte RESP parity against\n`redis-server`, and a real client-driver matrix (redis-py, go-redis, ioredis) in both\nsingle-node and cluster mode.\n\nThis project is also an experiment in method: it uses AI to mine prior art, propose\napproaches, and adversarially verify every load-bearing claim before trusting it. The\n[research corpus](docs/research/) and the version-pinned\n[`claims.yaml`](docs/prior-art/claims.yaml) are the output of that process.\n\n---\n\n## Features\n\n### Wire protocol and data types\n\n- **RESP2 and RESP3**, negotiated by `HELLO`, with the verbatim Redis error catalog.\n- **Strings and numerics**: GET/SET (with the full option set), GETSET, GETDEL,\n  GETEX, SETEX/PSETEX/SETNX, APPEND, STRLEN, GETRANGE/SETRANGE/SUBSTR,\n  INCR/DECR/INCRBY/DECRBY/INCRBYFLOAT, MGET/MSET/MSETNX.\n- **TTL / expiry**: EXPIRE/PEXPIRE/EXPIREAT/PEXPIREAT, TTL/PTTL,\n  EXPIRETIME/PEXPIRETIME, PERSIST, with active and lazy reaping.\n- **Lists**: LPUSH/RPUSH(/X), LPOP/RPOP, LRANGE, LINDEX, LSET, LINSERT, LREM, LTRIM,\n  LPOS, LMOVE/RPOPLPUSH, LMPOP.\n- **Hashes**: HSET/HMSET/HSETNX, HGET/HMGET/HGETALL/HKEYS/HVALS, HDEL, HLEN, HEXISTS,\n  HSTRLEN, HINCRBY/HINCRBYFLOAT, HRANDFIELD, HSCAN.\n- **Sets**: SADD/SREM, SMEMBERS, SISMEMBER/SMISMEMBER, SCARD, SPOP, SRANDMEMBER,\n  SMOVE, SINTER/SUNION/SDIFF (and the STORE + CARD variants), SSCAN.\n- **Sorted sets**: ZADD, ZREM, ZSCORE/ZMSCORE, ZRANK/ZREVRANK, ZINCRBY, ZCARD,\n  ZCOUNT/ZLEXCOUNT, the full ZRANGE family (by index/score/lex, plus ZRANGESTORE),\n  ZPOPMIN/ZPOPMAX, ZMPOP, ZRANDMEMBER, ZUNION/ZINTER/ZDIFF (and the STORE / CARD\n  variants), ZREMRANGEBY*, ZSCAN.\n- **Bitmaps**: SETBIT/GETBIT, BITCOUNT, BITPOS, BITOP, BITFIELD/BITFIELD_RO.\n- **HyperLogLog**: PFADD, PFCOUNT, PFMERGE (Redis-compatible dense representation).\n- **Generic keyspace**: DEL/UNLINK, EXISTS, TYPE, KEYS, SCAN, DBSIZE, RANDOMKEY,\n  RENAME/RENAMENX, COPY, MOVE, SWAPDB, TOUCH, FLUSHDB/FLUSHALL, OBJECT, SORT/SORT_RO.\n\n### Transactions, pub/sub, and blocking\n\n- **Transactions**: MULTI/EXEC/DISCARD with WATCH/UNWATCH dirty-CAS.\n- **Pub/Sub**: SUBSCRIBE/PSUBSCRIBE/UNSUBSCRIBE/PUNSUBSCRIBE, PUBLISH, PUBSUB\n  introspection, fanned out across shards by a cross-shard coordinator.\n- **Keyspace notifications**: the Redis `notify-keyspace-events` keyspace and\n  keyevent events (including `expired` / `evicted`), delivered through the same\n  Pub/Sub fan-out. Disabled by default; the write hot path pays nothing until a flag\n  is set.\n- **Blocking commands**: BLPOP/BRPOP, BLMOVE/BRPOPLPUSH, BLMPOP, BZPOPMIN/BZPOPMAX,\n  BZMPOP, and WAIT.\n\n### Architecture\n\n- **Thread-per-core, shared-nothing**: each shard is owned by one pinned core and\n  mutated by it alone, so there are no hot-path locks. Rust ownership makes the \"one\n  core owns one shard\" rule a compile-time guarantee.\n- **Per-shard accept** via `SO_REUSEPORT`, with a cross-shard coordinator for\n  multi-key, whole-keyspace, and pub/sub commands.\n- **A swappable Runtime seam**: the data path is written against a `Runtime` trait,\n  with a portable tokio (epoll/kqueue) implementation and an **optional io_uring\n  datapath** on Linux (default-off, opt-in) behind the same seam.\n- **Eviction**: a `maxmemory` ceiling with a configurable policy (default\n  `allkeys-lru`).\n\n### Durability and persistence\n\n- **On-disk snapshot**: SAVE / BGSAVE / LASTSAVE write a per-shard snapshot\n  (`dump-shard-\u003cn\u003e.icss`) plus a manifest under `data_dir`.\n- **Load on boot**: a node with a `data_dir` restores its keyspace at startup;\n  `/readyz` does not report ready until every shard has finished loading.\n- **Save policy**: `save_interval_secs` + `save_min_changes` (the Redis\n  `save \u003cseconds\u003e \u003cchanges\u003e` cadence), with a final save on graceful shutdown.\n- **Write-side durability bound** in a cluster: `min-replicas-to-write` /\n  `min-replicas-max-lag` (Redis-style, default off) refuses a write (`-NOREPLICAS`)\n  unless enough replicas are in sync, bounding the failover loss window.\n\n### Clustering and high availability (opt-in)\n\n- **Raft-governed control plane**: the 16384-slot ownership map, the config epoch,\n  the node roster, and replica roles live in a replicated log. User data never enters\n  the Raft log; only the cluster control state does.\n- **Slot routing**: CRC16 slot hashing (Redis-identical), with `-MOVED` and `-ASK`\n  redirects exactly like Redis Cluster.\n- **Replication**: asynchronous per-slot replication with a forkless full-sync, plus\n  bounded-staleness **read-replicas** (a `READONLY` client reads a replica only while\n  it is within the lag bound, otherwise the read `MOVED`s to the owner).\n- **Automatic failover**: an in-sync replica is promoted through a committed\n  `PromoteReplica` entry (a stale replica is never promoted); the committed apply is\n  the fence, so a promotion never creates two owners.\n- **Online slot migration**: `MIGRATING` / `IMPORTING` + `ASK` / `ASKING` + a single\n  committed ownership flip, with zero downtime and exactly one owner at the flip\n  boundary.\n- **Turnkey formation**: in raft mode a fresh cluster auto-applies its static\n  topology (node table + slot ownership) through the log and reaches\n  `cluster_state:ok` with no operator `CLUSTER MEET` / `ADDSLOTS`; the auto-apply is\n  fresh-only and idempotent, so a restart never re-bootstraps.\n- **Robustness**: Pre-Vote and check-quorum, a chunked `InstallSnapshot` path to\n  catch up a far-behind or newly added node, a disk-backed (spillable) replication\n  backlog with incremental resume, runtime voter-set reconfiguration with learners,\n  and leader-hint forwarding (a follower forwards a cluster proposal to the leader and\n  relays the commit).\n- **Split-brain fence**: slot ownership moves only through the committed Raft log, and\n  every change bumps a monotonic config epoch, so there is never a committed state\n  with two owners of a slot. The failure-prone paths are proven in a deterministic\n  simulation over thousands of seeded partition/crash/heal timelines, exercised over\n  real TCP loopback, and validated end to end on a live multi-process AWS cluster.\n\nThe default single-node and static-topology paths are **byte-unchanged** when\nclustering is off; a node run without `cluster_mode = \"raft\"` pays zero new hot-path\ncost. See [Clustering and high availability](docs/design/) and `DEPLOY.md` for the\nfull contract.\n\n### Security\n\n- **AUTH / requirepass**, stored as a SHA-256 digest **at rest** (never plaintext)\n  and compared in constant time.\n- **Full ACL**: per-user enable/disable, password rules, command and category rules\n  (`+@read`, `-@dangerous`, ...), key patterns, and channel patterns, via\n  `ACL SETUSER/GETUSER/DELUSER/LIST/USERS/CAT/WHOAMI/GENPASS/LOAD/SAVE`, with an\n  optional `aclfile`. ACL passwords are SHA-256 at rest.\n- **TLS** on three planes: the public client port (`tls`), the **cluster bus**, and\n  the **replication** link (`cluster_tls`, with peer-cert verification against a CA).\n- **Cluster peer auth**: a shared `cluster_secret` presented in a constant-time\n  handshake on the bus and replication links.\n- **Secret hygiene**: secret arguments are redacted from SLOWLOG, MONITOR, INFO, and\n  logs; the long-lived `cluster_secret` and transient plaintext are held in\n  `Zeroizing` and scrubbed from the heap. The scope (what is and is not protected, and\n  why) is documented in `SECURITY.md` and `docs/THREAT_MODEL.md`.\n\n### Operability\n\n- **HTTP health and metrics** (when `--metrics-addr` is set): `/livez` (liveness),\n  `/readyz` (ready only when every shard has loaded and, in raft mode, a leader is\n  known), and `/metrics` (Prometheus exposition: per-shard counters plus process and\n  raft gauges).\n- **Introspection**: INFO, CLIENT, COMMAND (a real command table for cluster-aware\n  clients), CLUSTER, OBJECT, SLOWLOG, MEMORY, LATENCY.\n- **DoS guards**: `maxmemory` with eviction, `maxclients`, an idle-connection\n  timeout, and a per-connection output-buffer bound.\n\n### Seamless upgrades\n\n- **`ironcache upgrade`**: a verified, data-safe, self-rolling-back binary self-update\n  that swaps a running node to a new version. It verifies the new artifact (SHA-256\n  against `SHA256SUMS`, behind a pluggable verifier seam for signature anchors), takes\n  an fsync'd snapshot first, swaps the binary atomically while keeping exactly one\n  rollback slot (the live path is never absent, even if the process is killed\n  mid-swap), restarts the node, and health-gates the result: `/readyz`, a real\n  process-restart proof (the `ironcache_uptime_seconds` reset, so a no-op restart or a\n  stale process cannot false-pass), a version match, and a stabilization window. Any\n  miss auto-rolls-back to the previous binary.\n- **Lossless across the restart**: before the snapshot it issues a node-wide\n  `CLIENT PAUSE WRITE` (writes hold; reads and admin like SAVE keep serving) so no\n  acknowledged write is lost in the save-to-reload window; `--no-freeze` opts out. A\n  failed upgrade unpauses and leaves the node untouched.\n- Validated end to end on a live AWS node: an upgrade under continuous concurrent\n  writes preserved every acknowledged write, the full keyspace, and the ACL users.\n\n### Deployment\n\n- A multi-stage, non-root, distroless container image (`Dockerfile`) published to\n  GHCR.\n- A **Helm chart** (`deploy/helm/ironcache`) and equivalent raw **Kubernetes**\n  manifests (`deploy/k8s/`), deploying a StatefulSet with headless + client Services,\n  a PDB, a PVC for `data_dir`, and `/livez` + `/readyz` probes.\n- **docker-compose** for a single node and a 3-node Raft cluster (`deploy/compose/`).\n- **CalVer rolling releases** on every push to `main` plus formal `v*` releases:\n  reproducible `musl` + `glibc` tarballs for **amd64 and arm64**, a consolidated\n  `SHA256SUMS`, a CycloneDX SBOM, and a keyless Sigstore build-provenance attestation.\n\nSee [`DEPLOY.md`](DEPLOY.md) for the full deployment guide, every config key, the\nports, and what was validated offline versus on a live cluster.\n\n---\n\n## Compatibility\n\nIronCache speaks RESP2 and RESP3 and honors the observable Redis contract for the\ncommands it implements. Compatibility is tiered and explicit: a command is either\nsupported with Redis-identical semantics, or it is documented as unsupported. We do\nnot bend the wire protocol or a command's observable behavior to win a benchmark.\n\n- **Differential-tested**: a harness drives identical command streams at IronCache and\n  a real `redis-server` and asserts byte-for-byte RESP equality, so a divergence\n  surfaces as a reviewable failure (see\n  [docs/design/DIFFERENTIAL_TESTING.md](docs/design/DIFFERENTIAL_TESTING.md)).\n- **Real client drivers validated** in both single-node and cluster mode (54 checks,\n  all passing): **redis-py 6.4.0**, **go-redis v9.7.0**, and **ioredis 5.11.1**. The\n  cluster checks confirm topology discovery via `CLUSTER SLOTS` and `MOVED`-routing\n  end to end. The one documented gap is a client limitation, not an IronCache defect:\n  ioredis is RESP2-only and cannot decode the RESP3 map byte (redis-py and go-redis\n  negotiate RESP3 against the same server cleanly). The full matrix is in\n  [tests/drivers/DRIVER_MATRIX.md](tests/drivers/DRIVER_MATRIX.md).\n\nA few deliberate model differences from single-node Redis are documented rather than\nsilently wrong: a single-node MULTI/EXEC (and a cross-shard multi-key move) requires\nthe keys to share a shard, mirroring the cluster contract that a transaction's keys\nmust share a slot (co-locate them with a `{hash tag}`).\n\n---\n\n## Quick start\n\n### Build and run from source\n\nYou need a stable Rust toolchain (MSRV 1.85, edition 2024).\n\n```sh\ncargo build --workspace\ncargo test --workspace          # 1,500+ tests\n\n# boot the server on every core (sharded, thread-per-core) and talk to it with any\n# Redis client\ncargo run -p ironcache -- server\nredis-cli -p 6379 SET hello world   # -\u003e OK\nredis-cli -p 6379 GET hello         # -\u003e \"world\"\n\n# other modes: the built-in CLI, the effective config, a config self-check, or a\n# verified data-safe binary self-upgrade (see \"Seamless upgrades\")\ncargo run -p ironcache -- cli GET hello\ncargo run -p ironcache -- config\ncargo run -p ironcache -- check\ncargo run -p ironcache -- upgrade --binary ./ironcache --sha256sums ./SHA256SUMS\n```\n\n### Run the container\n\n```sh\ndocker run -d --name ironcache \\\n  -p 6379:6379 -p 9121:9121 \\\n  -v ironcache-data:/var/lib/ironcache \\\n  -e IRONCACHE_DATA_DIR=/var/lib/ironcache \\\n  ghcr.io/elares/ironcache:latest \\\n  server --bind 0.0.0.0 --metrics-addr 0.0.0.0:9121\n\nredis-cli -p 6379 ping\ncurl localhost:9121/readyz\n```\n\n### Configuration\n\nConfiguration is layered, highest precedence first:\n\n```\nruntime CONFIG SET  \u003e  CLI flags  \u003e  IRONCACHE_* env vars  \u003e  TOML file  \u003e  built-in defaults\n```\n\nThe most common knobs (every key, with its env var, is in\n[`DEPLOY.md`](DEPLOY.md)):\n\n| Key (TOML) | Env var | Meaning |\n| --- | --- | --- |\n| `bind` / `port` | `IRONCACHE_BIND` / `IRONCACHE_PORT` | listen address and client port (default 6379) |\n| `shards` | `IRONCACHE_SHARDS` | per-core runtimes (default = available parallelism) |\n| `maxmemory` / `maxmemory-policy` | `IRONCACHE_MAXMEMORY` / `..._POLICY` | memory ceiling + eviction policy |\n| `maxclients` | `IRONCACHE_MAXCLIENTS` | max connections (default 10000) |\n| `requirepass` | `IRONCACHE_REQUIREPASS` | client AUTH password (hashed at rest) |\n| `aclfile` | `IRONCACHE_ACLFILE` | ACL users loaded at boot |\n| `data_dir` | `IRONCACHE_DATA_DIR` | durable snapshot + Raft-log dir (enables persistence) |\n| `save_interval_secs` / `save_min_changes` | `IRONCACHE_SAVE_*` | periodic save cadence |\n| `tls` + `tls_cert_path` + `tls_key_path` | `IRONCACHE_TLS*` | TLS on the client port |\n| `cluster_enabled` / `cluster_mode` | `IRONCACHE_CLUSTER_*` | turn on clustering; `static` or `raft` |\n| `cluster_secret` / `cluster_tls` | `IRONCACHE_CLUSTER_SECRET` / `_TLS` | peer auth + bus/repl encryption |\n| `min_replicas_to_write` | `IRONCACHE_MIN_REPLICAS_TO_WRITE` | write-side durability guardrail |\n\nIn raft mode the cluster-bus port is `port + 10000` and the replication port is\n`port + 20000`, both derived automatically.\n\n---\n\n## Benchmarks\n\nIronCache is built to be measured, not asserted. The run below is a multi-engine\nhead-to-head on AWS Graviton, dated 2026-06-21.\n\n**Setup.** Server nodes are **t4g.medium** (2 vCPU / 4 GB, arm64, AL2023); the load\ngenerator is a separate **t4g.2xlarge**. The tool is `memtier_benchmark` against\n32-byte values over a 1,000,000-key space, pipeline 16 for throughput and pipeline 1\nfor latency, peak across a connection sweep, persistence off. Each engine is given\nboth cores (Redis `io-threads 2`, KeyDB `server-threads 2`, Dragonfly\n`proactor_threads 2`, IronCache `shards 2`). Versions: Redis 7.4.1, KeyDB 6.3.4,\nDragonfly v1.39.0, IronCache (this build).\n\n### Single node, peak ops/sec\n\n| Workload | Redis 7.4 | KeyDB 6.3 | Dragonfly 1.39 | IronCache |\n| --- | ---: | ---: | ---: | ---: |\n| SET | 570,912 | 361,198 | 517,079 | **596,495** |\n| GET | 610,241 | 347,058 | 529,331 | **642,425** |\n| MIX 1:10 | **574,344** | 346,011 | 453,481 | 562,124 |\n| INCR | **924,908** | 541,577 | 548,804 | 663,373 |\n| GET p99 ms (pipeline 1) | 0.447 | 0.455 | 0.431 | **0.407** |\n\n### 3-node cluster, peak ops/sec\n\n| Workload | Redis 7.4 | KeyDB 6.3 | Dragonfly 1.39 | IronCache |\n| --- | ---: | ---: | ---: | ---: |\n| SET | **1,223,353** | 665,630 | 1,026,420 | 1,067,433 |\n| GET | 1,298,207 | 1,011,979 | 1,104,863 | **1,298,452** |\n| MIX 1:10 | **1,222,915** | 969,486 | 936,071 | 1,057,888 |\n\n### How to read this (honestly)\n\nThese are small (2-vCPU) nodes, chosen deliberately. On only two cores the\nmulti-threaded engines have very limited headroom, so single-threaded Redis stays\nextremely competitive and in fact **wins the tiny-payload commands** (INCR\nsingle-node, SET and MIX on the cluster) where its hand-tuned single-thread core has\nthe least overhead to amortize.\n\nWhere IronCache leads: it **tops SET and GET throughput and GET tail latency\nsingle-node**, and it **ties Redis on cluster GET (about 1.30M ops/sec)** while\nstaying clearly ahead of KeyDB and Dragonfly across the board. The picture is honest\nin both directions: Redis wins the small-op rows, IronCache wins the bulk SET/GET and\nlatency rows, and the two multi-threaded incumbents (KeyDB, Dragonfly) trail on these\nnodes.\n\nHigher-core nodes would widen the multi-threaded engines' lead over single-threaded\nRedis; this run intentionally used small nodes to show the worst case for a\nthread-per-core design, not its best. Reproduce a row with `memtier_benchmark` (32-byte\nvalues, 1M keyspace, `--pipeline 16` for throughput / `--pipeline 1` for latency, both\ncores per engine), sweeping connections for the peak.\n\n---\n\n## Repository layout\n\n- [README.md](README.md): this overview.\n- [DEPLOY.md](DEPLOY.md): the production deployment guide (container, Helm, k8s,\n  compose) and every config key.\n- [SECURITY.md](SECURITY.md) and [docs/THREAT_MODEL.md](docs/THREAT_MODEL.md): the\n  security policy and threat model.\n- [CHANGELOG.md](CHANGELOG.md): notable changes.\n- [docs/design/](docs/design/): the per-subsystem design records (protocol, runtime,\n  persistence, ACL, TLS, clustering, observability, ...).\n- [docs/adr/](docs/adr/): the architecture decision records.\n- [docs/PRIOR_ART.md](docs/PRIOR_ART.md) and\n  [docs/prior-art/claims.yaml](docs/prior-art/claims.yaml): the version-pinned\n  comparative survey and the single source of truth for every numeric prior-art claim.\n- [docs/bench/](docs/bench/): the competitor matrix and the optimization log.\n- The [GitHub issues](https://github.com/ELares/IronCache/issues): the design record,\n  indexed from the [vision EPIC (#1)](https://github.com/ELares/IronCache/issues/1).\n\n---\n\n## Contributing\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md) and [GOVERNANCE.md](GOVERNANCE.md). Prose in\nthis project uses no em dashes or en dashes.\n\n## License\n\nDual-licensed under your choice of [MIT](LICENSE-MIT) or\n[Apache-2.0](LICENSE-APACHE). Copyright is held collectively by\n\"The IronCache Authors\".\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Felares%2Fironcache","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Felares%2Fironcache","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Felares%2Fironcache/lists"}