NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
crates.io · #730 most downloaded on crates.io
A fast and concurrent cache library inspired by Java Caffeine
Last release 1 months ago
09 Aug 2026
Release timing varies
gaps range from 2 weeks to 9 months
Rarely documented
notes for 6 of the last 60 stable releases
4 versions withdrawn
withdrawn after publishing
6 years old
68 releases · first in 2020
One column per quarter.
Fixed a bug where cache eviction could stall permanently when the cache was configured with the non-default LRU eviction policy ( EvictionPolicy::lru(
EvictionPolicy::lru()) by a race between insert and remove operations on the same key (#592 by @kim-jhyeon, reported in #590):
sync::Cache, sync::SegmentedCache and future::Cache.max_capacity.entry_count and weighted_size to over-report and the usable capacity to shrink by one entry per occurrence. Fixed by the same change.fence(Acquire) in the internal MiniArc's drop path with an Acquire load of the reference count, so that downstream projects can now run ThreadSanitizer on code using Moka without hitting this false positive.std::sync::Arc has a similar workaround.crossbeam-epoch crate from v0.9.18 to v0.9.20 to avoid the following advisory (#603):
fmt::Pointer for Atomic and Sharedcrossbeam-epoch version via Moka.Fixed a bug where re-inserting an expired entry could cause it to lose its expiration time and remain in the cache indefinitely when using a custom Ex
Expiry policy with per-entry expiration. (#582 by @jiangzhe, #581 by @atrocities, reported in #575):
expire_after_update returned None. This primarily affected users who only override expire_after_create, since the default expire_after_update returns duration_until_expiry, which is None for expired entries.Expiry::expire_after_update was called.Expiry::expire_after_create is called instead.Expiry trait implementation.cht::segment::tests::drop_many_values and drop_many_values_concurrent that were failing on high-core-count machines (#586):
Expiry
policy with per-entry expiration. ([#582][gh-pull-0582] by [@jiangzhe][gh-jiangzhe],
[#581][gh-pull-0581] by [@atrocities][gh-atrocities], reported in
[#575][gh-issue-0575]):
expire_after_update returned None. This primarily
affected users who only override expire_after_create, since the default
expire_after_update returns duration_until_expiry, which is None for
expired entries.Expiry::expire_after_update was called.Expiry::expire_after_create is called instead.Expiry trait implementation.cht::segment::tests::drop_many_values and
drop_many_values_concurrent that were failing on high-core-count machines
([#586][gh-pull-0586]):
run_flaky_tests cfg
([#584][gh-pull-0584]):
crossbeam-epoch) timing
that is not guaranteed, causing intermittent failures.RUSTFLAGS='--cfg run_flaky_tests'.Fixed a race condition in the and_compute_with method in the future::Cache . ( #574 by @Squadrick ):
and_compute_with method in the future::Cache. (#574 by @Squadrick):
f closure may read a stale value, causing the first update to be lost when it is overwritten by a later one.dep: keyword in the crate features. (#577 by @alexanderkjall).and_compute_with method in the future::Cache.
([#574][gh-pull-0574] by [@Squadrick][gh-Squadrick]):
f closure may
read a stale value, causing the first update to be lost when it is overwritten
by a later one.dep: keyword in the crate features. ([#577][gh-pull-0577] by
[@alexanderkjall][gh-alexanderkjall]).Fixed/mitigated use-after-free issues in the hierarchical timer wheels when Expiry returns None (Issue #565 , reported by @sharksforarms ).
Expiry returns None (Issue #565, reported by @sharksforarms).
Expiry::expire_after_update not clearing expiration time for expired entries (future::Cache: #549, by @singulared, sync::Cache: #564).Expiry
returns None (Issue [#565][gh-issue-0565], reported by
[@sharksforarms][gh-sharksforarms]).
Expiry::expire_after_update not clearing expiration time for expired entries
(future::Cache: [#549][gh-pull-0549], by [@singulared][gh-singulared],
sync::Cache: [#564][gh-pull-0564]).Bumped the minimum supported Rust version (MSRV) to 1.71.1, released on August 3, 2023 ( #555 ).
Bumped the minimum supported Rust version (MSRV) to 1.71.1, released on August 3, 2023 (#555).
Expiry returns None (#548, by @awarus).deque::move_to_back method (found by Miri) (#553).Bumped the minimum supported Rust version (MSRV) to 1.71.1, released on August 3, 2023 ([#555][gh-pull-0555]).
Expiry
returns None ([#548][gh-pull-0548], by [@awarus][gh-awarus]).deque::move_to_back method
(found by Miri) ([#553][gh-pull-0553]).impl Expiry for some types ([#519][gh-pull-0519], by [@koushiro][gh-koushiro]).once_cell crate from the dependencies ([#520][gh-pull-0520], by
[@Expyron][gh-Expyron]).rustc_version crate from the dev-dependencies ([#554][gh-pull-0554]).This will make GitHub Dependabot to stop alerting about a security advisory [CVE-2022-23639][ghsa-qc84-gqf4-9926] for crossbeam-utils versions < 0.8.7…
Equivalent trait was an
unintended breaking change.
&*key.
error[E0277]: the trait bound `T: Borrow<Arc<T>>` is not satisfied
...
= note: required for `Arc<T>` to implement `Equivalent<T>`
Equivalent trait for the key type K of the caches.
(#492)jittered_expiry_policy example (#489).Cargo.toml was changed from
MIT OR Apache-2.0 to (MIT OR Apache-2.0) AND Apache-2.0.crossbeam-channel crate from v0.5.5 to
v0.5.15 to avoid the following issue (#514,
by karankurbur).
loom crate to a dev-dependency
(#509, by thomaseizinger).reqwest crate in the dev-dependencies from v0.11 to v0.12
(#531, by musicinmybrain).thiserror crate by manually implementing std::error::Error for
moka::PredicateError (#512, by @brownjohnf).paste crate from the dev-dependencies (#504).
async-std crate from the dev-dependencies (#534).
non_send_fields_in_send_ty that no longer applies
(#505, by @qti3e).quanta feature by default. (#482)quanta::Instant with std::time::Instant to increase the
accuracy of time measurements (#481):
quanta feature is enabled, quanta::Instant is used for some
performance critical parts in the cache, and std::time::Instant is used for
the rest of the parts.quanta feature will not make any
noticeable difference in the performance.quanta feature is disabled (default), std::time::Instant is used for
all time measurements.AtomicU64 of the portable-atomic crate, which provides fallback
implementations for platforms where std AtomicU64 is not available
(#480):
moka's atomic64 feature no longer has any effect on the build as
AtomicU64 is now always available on all platforms. But we keep the
atomic64 feature in Cargo.toml for backward compatibility.Bumped the minimum supported Rust version (MSRV) to 1.70 (June 1, 2023) (#474).
to_std_instant method when per-entry
expiration policy is used. (#472)and_try_compute_if_nobody_else method to future::Cache's entry API.
(#460, by @xuehaonan27)triomphe crate from the dependency by adding our own internal Arc type.
(#456)
Arc will be more memory efficient than std::sync::Arc or
triomphe::Arc on 64-bit platforms as it uses a single AtomicU32 counter.async-trait usage. (#445, by
@Swatinem)atomic64 feature only when target supports AtomicU64.
(#466, by @zonyitoo)once_cell dependency optional (#444).v0.1.12 or newer) of triomphe crate to keep our
MSRV (Minimum Supported Rust Version) at Rust 1.65
(#426, by @eaufavor).
triomphe@v0.1.12 requires Rust 1.76 or newer, so it will not compile with our
MSRV.run_pending_tasks to evict as many entries as possible
from the cache (#417).future::Cache that pending run_pending_tasks calls may cause
infinite busy loop in an internal schedule_write_op method
(#412):
v0.12.0 when the background threads were removed
from future::Cache.run_pending_task method is called by user code while
cache is receiving a very high number of concurrent cache write operations.
(e.g. insert, get_with, invalidate etc.)schedule_write_op method will be spinning in a busy loop
forever, causing high CPU usage and all other async tasks to be starved.async-lock crate used by future::Cache from v2.4 to the latest
v3.3.eviction_policy method of the cache
builder with a policy obtained by EvictionPolicy::lru function.crossbeam-epoch to run GC when dropping a cache (#384):
crossbeam-epoch crate provides an epoch-based memory reclamation scheme for
concurrent data structures. It is used by Moka cache to safely drop cached
entries while they are still being accessed by other threads.crossbeam-epoch does its best to reclaim memory (drop the entries evicted
from the cache) when the epoch is advanced. However, it does not guarantee that
memory will be reclaimed immediately after the epoch is advanced. This means
that entries can remain in the memory for a while after the cache is dropped.crossbeam-epoch's thread local buffers are flushed, helping to reclaim memory
immediately.crossbeam-epoch to improve this situation (e.g. #385).entry and entry_by_ref APIs have the following methods:
and_upsert_with method to insert or update the entry.and_compute_with method to insert, update, remove or do nothing on the
entry.and_try_compute_with method, which is similar to above but returns
Result.quanta from >=0.11.0, <0.12.0 to
>=0.12.2, <0.13.0 to avoid under-measuring the elapsed time on Apple silicon
Macs (#376).
entry_count method will keep returning a non
zero value after calling the invalidate_all method (which is also wrong).Note that both of #348 and #363 were already present
in v0.11.x and older versions. However they were less likely to occur because they
had background threads to periodically process pending tasks. So there were much
shorter time windows for these issues to occur.
future::Cache that occurred when get_with(),
entry().or_insert_with(), and similar methods were used (#329).
v0.12.0. Versions prior to v0.12.0 do not
have this bug.Note
v0.12.0has major breaking changes on the API and internal behavior.
sync caches are no longer enabled by default: Please use a crate feature
sync to enable it.
No more background threads: All cache types future::Cache, sync::Cache, and
sync::SegmentedCache no longer spawn background threads.
scheduled-thread-pool crate was removed from the dependency.future module were converted to async methods. You may need to add .await
to your code for those methods.Immediate notification delivery: The notification::DeliveryMode enum for the
eviction listener was removed. Now all cache types behave as if the Immediate
delivery mode is specified.
Please read the MIGRATION-GUIDE.md for more details.
future cache (#294) and sync
caches (#316).future::Cache. (#309)do_insert_with_hash method gets the current
Instant too early when eviction listener is enabled. (#322)sync::Cache and sync::SegmentedCache where memory usage kept
increasing when the eviction listener was set with the Immediate delivery mode.
(#295)Bumped the minimum supported Rust version (MSRV) to 1.65 (Nov 3, 2022). (#275)
num_cpus crate from the dependency. (#277)FrequencySketch in debug build.
(#272)examples directory. (#268, by
@peter-scholtens)sync and future caches can now allow
different expiration times for individual entries.remove method to the sync and future caches
(#255):
invalidate method, this method discards any cached value for the
key, but returns a clone of the value.NonNull pointer derived from a
shared reference. (#259)unsync cache that was marked as deprecated in v0.10.0.Bumped the minimum supported Rust version (MSRV) to 1.60 (Apr 7, 2022). (#252)
quanta crate to v0.11.0. (#251)
mach is unmaintained"
(#243) by replacing mach with mach2.quanta v0.11.0's MSRV is 1.60, so we also bumped the MSRV of Moka to 1.60.future cache's blocking().invalidate(key) method does not
trigger the eviction listener. (#242)sync and future caches will not cache anything when the max capacity is set
to zero (#230):
moka::unsync::Cache → mini_moka::unsync::Cachemoka::dash::Cache → mini_moka::sync::Cachesync and future caches
(#199). They were deprecated in v0.8.0:
get_or_insert_with (Use get_with instead)get_or_try_insert_with (Use try_get_with instead)sync and future caches have been marked as deprecated
(#193):
get_with_if (Use entry API's or_insert_with_if instead)entry and entry_by_ref APIs to sync and future caches
(#193):
or_defaultor_insertor_insert_withor_insert_with_ifor_optionally_insert_withor_try_insert_withEntry type, which provides is_fresh method to
check if the value was freshly computed or already existed in the cache.get_with method of future cache inflates future size by ~7x,
sometimes causing stack overflow (#212):
rustc optimization issue on async functions
(rust-lang/rust#62958).sync cache will disable
notifications. (#207)build_with_hasher method of cache builders.
(#216)get_with family methods to avoid evaluating init
closure or future multiple times in concurrent calls. (#195)optionally_get_with method to sync and future caches
(#187, by @LMJW):
try_get_with but takes an init closure/future returning an
Option<V> instead of Result<V, E>.by_ref version of API for get_with, optionally_get_with, and
try_get_with of sync and future caches (#190, by
@LMJW):
by_ref versions but take a reference of the key
instead of an owned key. If the key does not exist in the cache, the key will
be cloned to create new entry in the cache.sync or future cache (#177):
js feature to make unsync and sync caches to compile for
wasm32-unknown-unknown target (#173, by @aspect):
sync::Cachesync::SegmentedCachesync::Cachesync::SegmentedCachefuture::Cachesync and future caches under heavy loads on
many-core machine (#34):
Arc<K>: Borrow<Q> for the key &Q of the
contains_key, get and invalidate methods in the following caches (with K as
the key type) (#167). The requirement is now K: Borrow<Q> so these
methods will accept &[u8] for the key &Q when the stored key K is Vec<u8>.
sync::Cachesync::SegmentedCachefuture::Cachesync::Cachesync::SegmentedCachefuture::Cachesync for enabling and disabling sync caches.
(#141 by @Milo123459, and #143)
dash cache, opting out of sync will reduce the
number of dependencies.logging to enable optional log crate dependency.
(#159)
invalidate_all and invalidate_entries_if of the following
caches will not invalidate entries inserted just before calling them
(#155):
sync::Cachesync::SegmentedCachefuture::Cachedash::Cacheentry_count and weighted_size) methods to all caches.
(#137)Debug impl to the following caches (#138):
sync::Cachesync::SegmentedCachefuture::Cacheunsync::CacheK: Clone bound from the following caches when they are Clone
(#133):
sync::Cachefuture::Cachedash::Cacheget_with_if method to the following caches (#123):
sync::Cachesync::SegmentedCachefuture::CacheThe followings are internal changes to improve memory safety in unsafe Rust usages in Moka:
UnsafeWeakPointer from usize
to *mut T. (#127, by saethlin)sync::Cachesync::SegmentedCachefuture::Cacheunsync::CacheIntoIterator to the all caches (including experimental dash::Cache)
(#114)dash::Cache iterator not to return expired entries.
(#116)sync::SegmentedCache was created with
a non-power-of-two segments. (#117)contains_key method to check if a key is present without resetting the idle
timer or updating the historic popularity estimator. (#107)As a part of stabilizing the cache API, the following cache methods have been renamed:
get_or_insert_with(K, F) → get_with(K, F)get_or_try_insert_with(K, F) → try_get_with(K, F)Old methods are still available but marked as deprecated. They will be removed in a future version.
Also policy method was added to all caches and blocking method was added to
future::Cache. They return a Policy struct or BlockingOp struct
respectively. Some uncommon cache methods were moved to these structs, and old
methods were removed without deprecating.
Please see #105 for the complete list of the affected methods.
moka::dash::Cache, which uses dashmap::DashMap as the
internal storage. (#99)moka::dash::Cache. (#101)Please note that the above additions are highly experimental and their APIs will be frequently changed in next few releases.
The minimum supported Rust version (MSRV) is now 1.51.0 (Mar 25, 2021).
EntryInfo from enum to struct to reduce memory utilization.
(#76)std::sync::Arc usages with triomphe::Arc to reduce memory
utilization. (#80)CacheRegion value into a 2-bit tag space of TagNonNull pointer.
(#84)unstable-debug-counters feature for testing purpose. (#82)max_capacity has been changed from usize
to u64. This was necessary to have the weight-based cache management consistent
across different CPU architectures.get_or_insert_with and get_or_try_insert_with methods of
future::Cache, which caused a panic if previously inserting task aborted.
(#59)Send and 'static bounds from get_or_insert_with and
get_or_try_insert_with methods of future::Cache. (#53, by
@tinou98)get_or_insert_with and get_or_try_insert_with methods of
future::Cache and sync::Cache; a panic in the init future/closure
causes subsequent calls on the same key to get "unreachable code" panics.
(#43)get_or_try_insert_with to return a concrete error type rather
than a trait object. (#23, #37)armv5te-unknown-linux-musleabi or mips-unknown-linux-musl.
(#42, by @messense)std::sync::atomic::AtomicU64 is not
provided. (e.g. armv5te-unknown-linux-musleabi or mips-unknown-linux-musl)
(#38)
get_or_insert_with and get_or_try_insert_with methods of
future::Cache by adding missing bounds Send and 'static to the init
future. Without this fix, these methods will accept non-Send or
non-'static future and may cause undefined behavior.
(#31)usize overflow on big cache capacity. (#28)get_or_insert_with and get_or_try_insert_with
methods to the docs. (#30)get_or_insert_with and get_or_try_insert_with methods to sync and
future caches. (#20)sync::{Cache, SegmentedCache} and future::Cache
require Send, Sync and 'static for the generic parameters K (key),
V (value) and S (hasher state). This is necessary to prevent potential
undefined behaviors in applications using single-threaded async runtime such as
Actix-rt. (#19)invalidate_entries_if method to sync, future and unsync caches.
(#12)moka::unsync::Cache) and its builder for single-thread
applications. (#9)invalidate_all method to sync, future and unsync caches.
(#11)moka::future::Cache) and its builder.
(#7)moka::sync::{Cache, SegmentedCache}) with the following features:
<!-- Links -->
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Your coding agent can read these notes before it upgrades. Set up the MCP server →