{"id":24626547,"url":"https://github.com/foyer-rs/foyer","last_synced_at":"2026-01-23T09:33:01.426Z","repository":{"id":164262240,"uuid":"639698167","full_name":"foyer-rs/foyer","owner":"foyer-rs","description":"Hybrid in-memory and disk cache in Rust","archived":false,"fork":false,"pushed_at":"2025-05-09T09:30:22.000Z","size":2753,"stargazers_count":902,"open_issues_count":69,"forks_count":42,"subscribers_count":8,"default_branch":"main","last_synced_at":"2025-05-13T12:02:12.397Z","etag":null,"topics":["cache","hybrid-cache","rust"],"latest_commit_sha":null,"homepage":"https://foyer.rs","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/foyer-rs.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2023-05-12T03:02:26.000Z","updated_at":"2025-05-12T20:02:55.000Z","dependencies_parsed_at":"2023-07-03T02:24:29.021Z","dependency_job_id":"ef99f116-58cc-421a-998f-6776d7356fff","html_url":"https://github.com/foyer-rs/foyer","commit_stats":null,"previous_names":["foyer-rs/foyer","mrcroxx/foyer"],"tags_count":20,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/foyer-rs%2Ffoyer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/foyer-rs%2Ffoyer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/foyer-rs%2Ffoyer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/foyer-rs%2Ffoyer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/foyer-rs","download_url":"https://codeload.github.com/foyer-rs/foyer/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253939184,"owners_count":21987411,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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","hybrid-cache","rust"],"created_at":"2025-01-25T04:49:06.029Z","updated_at":"2026-01-23T09:33:01.417Z","avatar_url":"https://github.com/foyer-rs.png","language":"Rust","funding_links":[],"categories":["Rust","rust"],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n    \u003cimg src=\"https://raw.githubusercontent.com/foyer-rs/foyer/main/etc/logo/slogan.min.svg\" /\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n    \u003ca href=\"https://foyer-rs.github.io/foyer\"\u003e\n        \u003cimg src=\"https://img.shields.io/website?url=https%3A%2F%2Ffoyer-rs.github.io/foyer\u0026up_message=foyer-rs.github.io/foyer\u0026down_message=website\u0026style=for-the-badge\u0026logo=htmx\" alt=\"docs.rs\" /\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://crates.io/crates/foyer\"\u003e\n        \u003cimg src=\"https://img.shields.io/crates/v/foyer?style=for-the-badge\u0026logo=crates.io\u0026labelColor=555555\" alt=\"crates.io\" /\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://docs.rs/foyer\"\u003e\n        \u003cimg src=\"https://img.shields.io/docsrs/foyer?style=for-the-badge\u0026logo=rust\u0026label=docs.rs\u0026labelColor=555555\" alt=\"docs.rs\" /\u003e\n    \u003c/a\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n    \u003cb\u003eTutorial \u0026 Document:\u003c/b\u003e\n    \u003ca href=\"https://foyer-rs.github.io/foyer\"\u003e\u003cb\u003ehttps://foyer-rs.github.io/foyer\u003c/b\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n# foyer\n\n![GitHub License](https://img.shields.io/github/license/foyer-rs/foyer)\n![Crates.io MSRV](https://img.shields.io/crates/msrv/foyer)\n[![CI](https://github.com/foyer-rs/foyer/actions/workflows/ci.yml/badge.svg)](https://github.com/foyer-rs/foyer/actions/workflows/ci.yml)\n[![License Checker](https://github.com/foyer-rs/foyer/actions/workflows/license-check.yml/badge.svg)](https://github.com/foyer-rs/foyer/actions/workflows/license-check.yml)\n[![codecov](https://codecov.io/github/foyer-rs/foyer/branch/main/graph/badge.svg?token=YO33YQCB70)](https://codecov.io/github/foyer-rs/foyer)\n\n*foyer* aims to be an efficient and user-friendly hybrid cache lib in Rust.\n\nfoyer draws inspiration from [Facebook/CacheLib](https://github.com/facebook/cachelib), a highly-regarded hybrid cache library written in C++, and [ben-manes/caffeine](https://github.com/ben-manes/caffeine), a popular Java caching library, among other projects.\n\nHowever, *foyer* is more than just a *rewrite in Rust* effort; it introduces a variety of new and optimized features.\n\nFor more details, please visit foyer's website: \u003chttps://foyer-rs.github.io/foyer\u003e 🥰\n\n[Website](https://foyer-rs.github.io/foyer) |\n[Tutorial](https://foyer-rs.github.io/foyer/docs/overview) |\n[API Docs](https://docs.rs/foyer) |\n[Crate](https://crates.io/crates/foyer)\n\n## Features\n\n- **Hybrid Cache**: Seamlessly integrates both in-memory and disk cache for optimal performance and flexibility.\n- **Plug-and-Play Algorithms**: Empowers users with easily replaceable caching algorithms, ensuring adaptability to diverse use cases.\n- **Fearless Concurrency**: Built to handle high concurrency with robust thread-safe mechanisms, guaranteeing reliable performance under heavy loads.\n- **Zero-Copy In-Memory Cache Abstraction**: Leveraging Rust's robust type system, the in-memory cache in foyer achieves a better performance with zero-copy abstraction.\n- **User-Friendly Interface**: Offers a simple and intuitive API, making cache integration effortless and accessible for developers of all levels.\n- **Out-of-the-Box Observability**: Integrate popular observation systems such as Prometheus, Grafana, Opentelemetry, and Jaeger in just *ONE* line.\n\n\u003c!-- rustdoc-ignore-start --\u003e\n\n## Projects Using *foyer*\n\nFeel free to open a PR and add your projects here:\n\n- [RisingWave](https://github.com/risingwavelabs/risingwave): SQL stream processing, analytics, and management.\n- [Chroma](https://github.com/chroma-core/chroma): Embedding database for LLM apps.\n- [SlateDB](https://github.com/slatedb/slatedb): A cloud native embedded storage engine built on object storage.\n- [ZeroFS](https://github.com/Barre/zerofs): File systems and block devices on S3 storage.\n- [Percas](https://github.com/scopedb/percas): A distributed persistent cache service optimized for high performance NVMe SSD.\n- [dna](https://github.com/apibara/dna): The fastest platform to build production-grade indexers that connect onchain data to web2 services.\n- [si](https://github.com/systeminit/si): The System Initiative software.\n- [AntTP](https://github.com/traktion/AntTP): Serves Autonomi Network data over HTTP protocol.\n- [Cachey](https://github.com/s2-streamstore/cachey): Read-through cache for object storage.\n\n\u003c!-- rustdoc-ignore-end --\u003e\n\n## Quick Start\n\n**This section only shows briefs. Please visit \u003chttps://foyer-rs.github.io/foyer\u003e for more details.**\n\nTo use *foyer* in your project, add this line to the `dependencies` section of `Cargo.toml`.\n\n```toml\nfoyer = \"0.22\"\n```\n\nIf your project is using the nightly rust toolchain, the `nightly` feature needs to be enabled.\n\n```toml\nfoyer = { version = \"0.22\", features = [\"nightly\"] }\n```\n\n### Out-of-the-box In-memory Cache\n\nThe in-memory cache setup is extremely easy and can be setup in at least 1 line.\n\n```rust\nuse foyer::{Cache, CacheBuilder};\n\nlet cache: Cache\u003cString, String\u003e = CacheBuilder::new(16).build();\n\nlet entry = cache.insert(\"hello\".to_string(), \"world\".to_string());\nlet e = cache.get(\"hello\").unwrap();\n\nassert_eq!(entry.value(), e.value());\n```\n\n### Easy-to-use Hybrid Cache\n\nThe setup of a hybrid cache is extremely easy.\n\n```rust\nuse foyer::{BlockEngineConfig, DeviceBuilder, FsDeviceBuilder, HybridCache, HybridCacheBuilder};\n\n#[tokio::main]\nasync fn main() -\u003e anyhow::Result\u003c()\u003e {\n    let dir = tempfile::tempdir()?;\n\n    let device = FsDeviceBuilder::new(dir.path())\n        .with_capacity(256 * 1024 * 1024)\n        .build()?;\n\n    let hybrid: HybridCache\u003cu64, String\u003e = HybridCacheBuilder::new()\n        .memory(64 * 1024 * 1024)\n        .storage()\n        // use block-based disk cache engine with default configuration\n        .with_engine_config(BlockEngineConfig::new(device))\n        .build()\n        .await?;\n\n    hybrid.insert(42, \"The answer to life, the universe, and everything.\".to_string());\n    assert_eq!(\n        hybrid.get(\u002642).await?.unwrap().value(),\n        \"The answer to life, the universe, and everything.\"\n    );\n\n    Ok(())\n}\n```\n\n### Fully Configured Hybrid Cache\n\nHere is an example of a hybrid cache setup with almost all configurations to show the possibilities of tuning.\n\n```rust\nuse std::{hash::BuildHasherDefault, num::NonZeroUsize};\n\nuse foyer::{\n    BlockEngineConfig, DeviceBuilder, FifoPicker, FsDeviceBuilder, HybridCache, HybridCacheBuilder, HybridCachePolicy,\n    IopsCounter, LruConfig, PsyncIoEngineConfig, RecoverMode, RejectAll, StorageFilter, Throttle,\n};\nuse tempfile::tempdir;\n\n#[tokio::main]\nasync fn main() -\u003e anyhow::Result\u003c()\u003e {\n    let dir = tempdir()?;\n\n    let device = FsDeviceBuilder::new(dir.path())\n        .with_capacity(64 * 1024 * 1024)\n        .with_throttle(\n            Throttle::new()\n                .with_read_iops(4000)\n                .with_write_iops(2000)\n                .with_write_throughput(100 * 1024 * 1024)\n                .with_read_throughput(800 * 1024 * 1024)\n                .with_iops_counter(IopsCounter::PerIoSize(NonZeroUsize::new(128 * 1024).unwrap())),\n        )\n        .build()?;\n\n    let hybrid: HybridCache\u003cu64, String\u003e = HybridCacheBuilder::new()\n        .with_name(\"my-hybrid-cache\")\n        .with_policy(HybridCachePolicy::WriteOnEviction)\n        .memory(1024)\n        .with_shards(4)\n        .with_eviction_config(LruConfig {\n            high_priority_pool_ratio: 0.1,\n        })\n        .with_hash_builder(BuildHasherDefault::default())\n        .with_weighter(|_key, value: \u0026String| value.len())\n        .with_filter(|_, _| true)\n        .storage()\n        .with_io_engine_config(PsyncIoEngineConfig::new())\n        .with_engine_config(\n            BlockEngineConfig::new(device)\n                .with_block_size(16 * 1024 * 1024)\n                .with_indexer_shards(64)\n                .with_recover_concurrency(8)\n                .with_flushers(2)\n                .with_reclaimers(2)\n                .with_buffer_pool_size(256 * 1024 * 1024)\n                .with_clean_block_threshold(4)\n                .with_eviction_pickers(vec![Box::\u003cFifoPicker\u003e::default()])\n                .with_admission_filter(StorageFilter::new())\n                .with_reinsertion_filter(StorageFilter::new().with_condition(RejectAll))\n                .with_tombstone_log(false),\n        )\n        .with_recover_mode(RecoverMode::Quiet)\n        .with_compression(foyer::Compression::Lz4)\n        .with_spawner(\n            tokio::runtime::Builder::new_multi_thread()\n                .enable_all()\n                .worker_threads(4)\n                .max_blocking_threads(2)\n                .build()\n                .unwrap()\n                .into(),\n        )\n        .build()\n        .await?;\n\n    hybrid.insert(42, \"The answer to life, the universe, and everything.\".to_string());\n    assert_eq!(\n        hybrid.get(\u002642).await?.unwrap().value(),\n        \"The answer to life, the universe, and everything.\"\n    );\n\n    let e = hybrid\n        .get_or_fetch(\u002620230512, || async {\n            // Mock fetching data from remote source\n            let now = jiff::Zoned::now();\n            if format!(\"{}{}{}\", now.year(), now.month(), now.day()) == \"20230512\" {\n                return Err(anyhow::anyhow!(\"Hi, time traveler!\"));\n            }\n            Ok(\"Hello, foyer.\".to_string())\n        })\n        .await?;\n    assert_eq!(e.key(), \u002620230512);\n    assert_eq!(e.value(), \"Hello, foyer.\");\n\n    hybrid.close().await?;\n    Ok(())\n}\n```\n\n### `serde` Support\n\n***foyer*** needs to serialize/deserialize entries between memory and disk with hybrid cache. Cached keys and values need to implement the `Code` trait when using hybrid cache.\n\nThe `Code` trait has already been implemented for general types, such as:\n\n- Numeric types: `u8`, `u16`, `u32`, `u64`, `u128`, `usize`, `i8`, `i16`, `i32`, `i64`, `i128`, `isize`, `f32`, `f64`.\n- Buffer: `Vec\u003cu8\u003e`.\n- String: `String`.\n- Other general types: `bool`.\n\nFor more complex types, you need to implement the Code trait yourself.\n\nTo make things easier, ***foyer*** provides support for the `serde` ecosystem. Types implement `serde::Serialize` and `serde::DeserializeOwned`, ***foyer*** will automatically implement the `Code` trait. This feature requires enabling the `serde` feature for foyer.\n\n```toml\nfoyer = { version = \"*\", features = [\"serde\"] }\n```\n\n### Other Examples\n\n- [Serialize/Deserialize w/wo serde](https://github.com/foyer-rs/foyer/tree/main/examples/serde.rs)\n- [Export Metrics with `prometheus` and `hyper`](https://github.com/foyer-rs/foyer/tree/main/examples/export_metrics_prometheus_hyper.rs)\n- [Tail-based Tracing](https://github.com/foyer-rs/foyer/tree/main/examples/tail_based_tracing.rs)\n\nMore code examples and details can be found [here](https://github.com/foyer-rs/foyer/tree/main/examples).\n\nCase study of real-world usage in the production system can be found in [Document - Case Study - RisingWave](https://foyer-rs.github.io/foyer/docs/case-study/risingwave)\n\n## Architecture\n\nThe architecture of ***foyer*** is still not mature and is undergoing rapid iteration. Currently, the architectural design can refer to [Document - Architecture](https://foyer-rs.github.io/foyer/docs/design/architecture)\n\n## Supported Rust Versions\n\n*foyer* is built against the recent stable release. The minimum supported version is 1.86.0. The current *foyer* version is not guaranteed to build on Rust versions earlier than the minimum supported version.\n\n## Supported Platforms\n\n*foyer* is designed to serve on Linux OS, but can still be built on other OS for development.\n\nHowever, other components may not support non-Linux OS.\n\n| Component   | Linux | MacOS | Windows |\n|-------------|-------|-------|---------|\n| foyer       | ✓     | ✓     | ✓       |\n| foyer-bench | ✓     | ✗     | ✗       |\n\n## Development State \u0026 Roadmap\n\nCurrently, *foyer* is still under heavy development.\n\nThe development state and the roadmap can be found in [foyer - Development Roadmap](https://github.com/orgs/foyer-rs/projects/2).\n\n## Contributing\n\nContributions for *foyer* are warmly welcomed! 🥰\n\nDon't forget to pass `cargo x --fast` (which runs most necessary checks and tests) locally before submitting a PR. 🚀\n\nIf you want to run a broader range of checks locally, run `cargo x`. 🙌\n\nThank you for your contribution~ \u003cimg src=\"https://raw.githubusercontent.com/foyer-rs/foyer/main/etc/logo/ferris.min.svg\" height=\"24px\" /\u003e\n\n\u003c!-- rustdoc-ignore-start --\u003e\n\n## Star History\n\n[![Star History Chart](https://api.star-history.com/svg?repos=foyer-rs/foyer\u0026type=Date)](https://www.star-history.com/#foyer-rs/foyer\u0026Date)\n\n\u003c!-- rustdoc-ignore-end --\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffoyer-rs%2Ffoyer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffoyer-rs%2Ffoyer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffoyer-rs%2Ffoyer/lists"}