{"id":39176872,"url":"https://github.com/verdie-g/modern-caching","last_synced_at":"2026-01-17T22:29:18.630Z","repository":{"id":130445236,"uuid":"347404644","full_name":"verdie-g/modern-caching","owner":"verdie-g","description":"Modern caching library for modern .NET","archived":false,"fork":false,"pushed_at":"2024-01-28T17:47:20.000Z","size":360,"stargazers_count":4,"open_issues_count":3,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-10-20T18:44:42.174Z","etag":null,"topics":["caching","database","dotnet","memcached","redis"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/verdie-g.png","metadata":{"files":{"readme":"README.md","changelog":null,"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}},"created_at":"2021-03-13T15:19:35.000Z","updated_at":"2025-10-20T12:36:41.000Z","dependencies_parsed_at":null,"dependency_job_id":"38720a51-5f45-4ea5-a221-3fc293fb458b","html_url":"https://github.com/verdie-g/modern-caching","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/verdie-g/modern-caching","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/verdie-g%2Fmodern-caching","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/verdie-g%2Fmodern-caching/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/verdie-g%2Fmodern-caching/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/verdie-g%2Fmodern-caching/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/verdie-g","download_url":"https://codeload.github.com/verdie-g/modern-caching/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/verdie-g%2Fmodern-caching/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28520529,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-17T22:11:28.393Z","status":"ssl_error","status_checked_at":"2026-01-17T22:11:27.841Z","response_time":85,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: 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":["caching","database","dotnet","memcached","redis"],"created_at":"2026-01-17T22:29:18.191Z","updated_at":"2026-01-17T22:29:18.624Z","avatar_url":"https://github.com/verdie-g.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ModernCaching\n\nA 2-layer, performant and resilient caching solution for modern .NET.\n\nA typical cache provided by this library consists of:\n- a synchronous local cache that implements [`ICache`](https://github.com/verdie-g/modern-caching/blob/main/src/ModernCaching/LocalCaching/ICache.cs)\n- an asynchronous distributed cache that implements [`IAsyncCache`](https://github.com/verdie-g/modern-caching/blob/main/src/ModernCaching/DistributedCaching/IAsyncCache.cs)\n  (e.g. memcache, redis)\n- a data source that implements [`IDataSource`](https://github.com/verdie-g/modern-caching/blob/main/src/ModernCaching/DataSource/IDataSource.cs)\n  (e.g. relational database, Web API, CPU intensive task...)\n\nThese 3 components form an [`IReadOnlyCache`](https://github.com/verdie-g/modern-caching/blob/main/src/ModernCaching/IReadOnlyCache.cs).\nThe 2 cache layers are populated from the\n[`IDataSource`](https://github.com/verdie-g/modern-caching/blob/main/src/ModernCaching/DataSource/IDataSource.cs)\nwith a backfilling mechanism when getting a value or by preloading some data\nwhen building the cache.\n\n![schema](https://user-images.githubusercontent.com/9092290/122583694-d5a59f00-d059-11eb-826b-6fd8011df3b0.png)\n\nModernCaching doesn't provide implementations of\n[`IAsyncCache`](https://github.com/verdie-g/modern-caching/blob/main/src/ModernCaching/DistributedCaching/IAsyncCache.cs)\nor [`IDataSource`](https://github.com/verdie-g/modern-caching/blob/main/src/ModernCaching/DataSource/IDataSource.cs)\nbecause they are usually tied to the business. Only a single implementation of\n[`ICache`](https://github.com/verdie-g/modern-caching/blob/main/src/ModernCaching/LocalCaching/ICache.cs)\nis built-in: \n[`MemoryCache`](https://github.com/verdie-g/modern-caching/blob/main/src/ModernCaching/LocalCaching/MemoryCache.cs).\n\nThis library is inspired by a component of the [Criteo](https://medium.com/criteo-engineering)'s\nSDK that handles 10B+ requests per second (hint: it's a lot). ModernCaching is production ready\nbut lacks a way to invalidate data ([#1](https://github.com/verdie-g/modern-caching/issues/1)).\n\n## Installation\n\nModernCaching is available on [Nuget](https://www.nuget.org/packages/ModernCaching).\n\n```\ndotnet add package ModernCaching\n```\n\n## Features\n\n- **Strict API**. [`IReadOnlyCache`](https://github.com/verdie-g/modern-caching/blob/main/src/ModernCaching/IReadOnlyCache.cs)\n  has only two methods:\n  - `TryPeek`, a synchronous operation to only get the value if it's present in\n    the local cache and refresh in the background if needed.\n  - `TryGetAsync`, an asynchronous operation to get the first fresh value in the\n    local cache, distributed cache or the data source, in that order.\n- **Performance**. Unlike other caching libraries that use a `string` as a key or an\n  `object` as value or both, `ModernCaching` uses a generic key and value. That\n  way, getting a value from the local cache doesn't require any allocation for\n  simple type keys such as `int` or more complex user-defined objects. See the\n  [benchmarks](https://github.com/verdie-g/modern-caching#benchmarks).\n- **Resilience**. With its fixed number of layers, each behavior is clearly\n  defined when one of these layers is down. For instance, the data source is\n  skipped if the distributed cache is unavailable to avoid DDOSing it.\n- **Instrumentation**. Metrics are exposed using [OpenTelemetry](https://opentelemetry.io) API.\n  Errors from user-code are logged if a logger is specified.\n\n## Example\n\nThis example caches the user information. The first layer is implemented with an\nin-memory cache, the second one is a redis where we specify how to create the\nkey and how to serialize the value using the interface `IKeyValueSerializer`.\nBehind these two layers stands the `IDataSource`.\n\n```csharp\nvar cache = await new ReadOnlyCacheBuilder\u003cGuid, User\u003e(new ReadOnlyCacheOptions(\"user_cache\", TimeSpan.FromMinutes(15))\n    .WithLocalCache(new MemoryCache\u003cGuid, User\u003e())\n    .WithDistributedCache(new RedisAsyncCache(redis), new ProtobufKeyValueSerializer\u003cGuid, User\u003e())\n    .WithDataSource(new UserDataSource(\"Host=localhost;User ID=postgres\"))\n    .BuildAsync();\n\nGuid userId = new(\"cb22ff11-4683-4ec3-b212-7f1d0ab378cc\");\nbool found = cache.TryPeek(userId, out User? user); // Only check local cache with background refresh.\n(bool found, User? user) = await cache.TryGetAsync(userId); // Check all layers for a fresh value.\n```\n\nThe rest of the code as well as other examples can be found in\n[src/ModernCaching.ITest](https://github.com/verdie-g/modern-caching/blob/main/src/ModernCaching.ITest).\n\n## Benchmarks\n\nBenchmark of the very hot path of different caching libraries\n([Microsoft.Extensions.Caching.Memory](https://learn.microsoft.com/en-us/dotnet/core/extensions/caching),\n[CacheTower](https://github.com/TurnerSoftware/CacheTower),\n[Foundatio](https://github.com/FoundatioFx/Foundatio),\n[LazyCache](https://github.com/alastairtree/LazyCache),\n[FusionCache](https://github.com/jodydonetti/ZiggyCreatures.FusionCache),\n[EasyCaching](https://github.com/dotnetcore/EasyCaching),\n[CacheManager](https://github.com/MichaCo/CacheManager)),\nthat is, getting locally cached data.\n\n| Method        | Mean      | Error    | StdDev   | Ratio | RatioSD | Allocated |\n|-------------- |----------:|---------:|---------:|------:|--------:|----------:|\n| ModernCaching |  13.58 ns | 0.018 ns | 0.015 ns |  1.00 |    0.00 |         - |\n| Microsoft     |  32.25 ns | 0.226 ns | 0.189 ns |  2.38 |    0.01 |      32 B |\n| CacheTower    |  64.98 ns | 0.368 ns | 0.345 ns |  4.79 |    0.03 |      96 B |\n| Foundatio     | 104.12 ns | 0.651 ns | 0.577 ns |  7.67 |    0.04 |     216 B |\n| LazyCache     |  77.99 ns | 0.636 ns | 0.594 ns |  5.74 |    0.04 |      96 B |\n| FusionCache   |  92.17 ns | 0.405 ns | 0.379 ns |  6.80 |    0.02 |     160 B |\n| EasyCaching   | 141.51 ns | 0.455 ns | 0.425 ns | 10.42 |    0.03 |     264 B |\n| CacheManager  | 247.69 ns | 2.767 ns | 2.453 ns | 18.27 |    0.16 |     344 B |\n\nThis library has similar performance as a raw ConcurrentDictionary since its hot\npath is a thin layer around it. It doesn't allocate anything, putting no pressure\non the garbage collector.\n\nCode can be found in [src/ModernCaching.Benchmarks](https://github.com/verdie-g/modern-caching/tree/main/src/ModernCaching.Benchmarks).\n\n## Telemetry\n\n### Metrics / Traces\n\nMetrics and traces are exposed using .NET implementation of the [OpenTelemetry API](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/api.md)\n([System.Diagnostics](https://docs.microsoft.com/en-us/dotnet/api/system.diagnostics))\nunder the source name `ModernCaching`. They can be exported using the\n[OpenTelemetry .NET SDK](https://github.com/open-telemetry/opentelemetry-dotnet).\n\n### Logs\n\nUse `WithLoggerFactory` on the builder to log all user-code errors coming from\n[`IAsyncCache`](https://github.com/verdie-g/modern-caching/blob/main/src/ModernCaching/DistributedCaching/IAsyncCache.cs),\n[`IKeyValueSerializer`](https://github.com/verdie-g/modern-caching/blob/main/src/ModernCaching/DistributedCaching/IKeyValueSerializer.cs) or\n[`IDataSource`](https://github.com/verdie-g/modern-caching/blob/main/src/ModernCaching/DataSource/IDataSource.cs).\n\n## License\n\nAll code found in this repository is licensed under MIT. See the\n[LICENSE](https://github.com/verdie-g/crpg/blob/master/LICENSE)\nfile in the project root for the full license text.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fverdie-g%2Fmodern-caching","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fverdie-g%2Fmodern-caching","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fverdie-g%2Fmodern-caching/lists"}