# How to Clone a Moka Cache in Rust: Thread-Safe Sharing Explained

> Learn how to clone a Moka cache in Rust using simple O(1) operations. Share thread-safe cache handles efficiently without copying data.

- Repository: [moka-rs/moka](https://github.com/moka-rs/moka)
- Tags: how-to-guide
- Published: 2026-03-07

---

**Cloning a Moka cache is a cheap, O(1) operation that creates new reference-counted handles to the same underlying data structures without copying stored entries.**

The `moka` crate provides high-performance concurrent caching for Rust applications. Whether you are using `moka::sync::Cache` or `moka::future::Cache`, understanding how to clone moka cache correctly allows you to share the same data store across threads or async tasks without external locking.

## How Cloning Works in Moka

According to the moka-rs/moka source code, both synchronous and asynchronous caches are built on **thread-safe reference-counted containers**. When you clone a cache, you are not duplicating the stored key-value pairs; you are simply incrementing reference counts on the internal **Arc** pointers.

### The Internal Architecture

In [`src/sync/cache.rs`](https://github.com/moka-rs/moka/blob/main/src/sync/cache.rs), a `Cache<K, V, S>` consists of two primary **Arc**-wrapped components:

- **`BaseCache<K, V, S>`**: Contains the concurrent hash table, eviction policies, and housekeeping data.
- **`Arc<ValueInitializer<K, V>>`**: Wraps the closure used for lazy value initialization.

Because these components live behind **Arc** pointers, cloning only requires incrementing reference counts. This design avoids adding `K: Clone` bounds on the cache itself while enabling cheap sharing.

### The Clone Implementation

The `Clone` trait implementation in [`src/sync/cache.rs`](https://github.com/moka-rs/moka/blob/main/src/sync/cache.rs) (lines 592-603) is deliberately handwritten rather than derived:

```rust
impl<K, V, S> Clone for Cache<K, V, S> {
    /// Makes a clone of this shared cache.
    ///
    /// This operation is cheap as it only creates thread‑safe reference counted
    /// pointers to the shared internal data structures.
    fn clone(&self) -> Self {
        Self {
            base: self.base.clone(),
            value_initializer: Arc::clone(&self.value_initializer),
        }
    }
}

```

This implementation ensures that all clones point to the same `BaseCache` instance. Any mutation—such as `insert` or `invalidate`—performed through one handle is immediately visible to all other handles.

## Basic Cloning Example

For the synchronous cache (`moka::sync::Cache`), cloning works exactly like any standard Rust clone:

```rust
use moka::sync::Cache;

fn main() {
    // Create a cache holding up to 10,000 entries
    let cache = Cache::new(10_000);
    
    // Cheap O(1) clone
    let cache2 = cache.clone();
    
    // Both handles share the same data
    cache.insert(1, "one".to_string());
    assert_eq!(cache2.get(&1), Some("one".to_string()));
}

```

Because the clone shares the same underlying storage, you can read values through one handle that were inserted through another without synchronization overhead.

## Sharing Across Multiple Threads

The primary use case for cloning is **zero-cost sharing** across threads. Since Moka handles concurrency internally, you never need a `Mutex` or `RwLock` around the cache:

```rust
use moka::sync::Cache;
use std::thread;

fn main() {
    let cache = Cache::new(5_000);
    
    // Spawn threads with cloned handles
    let handles: Vec<_> = (0..4)
        .map(|i| {
            let c = cache.clone();  // Cheap clone
            thread::spawn(move || {
                c.insert(i, i * 10);
                // Reads see all threads' inserts
                assert_eq!(c.get(&i), Some(i * 10));
            })
        })
        .collect();
    
    for h in handles {
        h.join().expect("thread panicked");
    }
    
    // Original cache sees all inserts
    for i in 0..4 {
        assert_eq!(cache.get(&i), Some(i * 10));
    }
}

```

This pattern applies to both the standard cache and the `SegmentedCache` variant found in [`src/sync/segment.rs`](https://github.com/moka-rs/moka/blob/main/src/sync/segment.rs).

## Cloning the Async Cache

The asynchronous `moka::future::Cache` (defined in [`src/future/cache.rs`](https://github.com/moka-rs/moka/blob/main/src/future/cache.rs)) follows the same cloning semantics. It is safe to clone across async boundaries and tasks:

```rust
use moka::future::Cache;
use tokio::runtime::Runtime;

fn main() {
    let rt = Runtime::new().unwrap();
    rt.block_on(async {
        let cache = Cache::builder()
            .max_capacity(1_000)
            .weigher(|_k: &u64, v: &String| v.len() as u32)
            .build();
        
        // Clone the async cache
        let cache2 = cache.clone();
        
        cache.insert(42, "answer".to_string()).await;
        assert_eq!(cache2.get(&42).await, Some("answer".to_string()));
    });
}

```

The async implementation mirrors the sync API, using identical **Arc**-based cloning to maintain **O(1)** performance characteristics.

## Summary

- **Cheap operation**: Cloning a Moka cache only increments **Arc** reference counts in [`src/sync/cache.rs`](https://github.com/moka-rs/moka/blob/main/src/sync/cache.rs), making it an **O(1)** operation regardless of cache size.
- **Shared state**: All clones reference the same `BaseCache` instance, so changes are visible across all handles immediately.
- **Thread safety**: The design requires no external locking—Moka's internal concurrent hash table handles synchronization.
- **Universal pattern**: Both `moka::sync::Cache` and `moka::future::Cache` (and `SegmentedCache`) implement identical cloning behavior through **Arc** pointers.
- **No trait bounds**: The manual `Clone` implementation avoids requiring `K: Clone` on your key types.

## Frequently Asked Questions

### Does cloning a Moka cache copy all the stored entries?

No. Cloning creates new handles to the same underlying data structures via **Arc** pointers. The stored entries remain in the shared `BaseCache` instance defined in [`src/sync/base_cache.rs`](https://github.com/moka-rs/moka/blob/main/src/sync/base_cache.rs), so no key-value pairs are duplicated in memory.

### Is it safe to clone a Moka cache and send it to another thread?

Yes. `moka::sync::Cache` implements both `Clone` and `Send`, allowing you to safely move clones across thread boundaries. The cache handles all internal synchronization, so you do not need to wrap it in `Mutex` or `Arc` yourself.

### Do cache configuration settings persist after cloning?

Yes. Since configuration (capacity, eviction policy, weigher) is stored inside the shared `BaseCache`, all clones inherit the same settings. Modifying the configuration through one handle affects the behavior of all other handles.

### Can I clone the async cache (`moka::future::Cache`) the same way?

Yes. The async cache in [`src/future/cache.rs`](https://github.com/moka-rs/moka/blob/main/src/future/cache.rs) implements `Clone` identically to the synchronous version. You can safely clone it before spawning async tasks or moving it between runtimes.