# Moka Cache Key Types Supported: Trait Bounds and Examples

> Explore Moka cache key types. Moka supports Hash Eq Send Sync 'static keys without requiring Clone for efficient Rust caching.

- Repository: [moka-rs/moka](https://github.com/moka-rs/moka)
- Tags: api-reference
- Published: 2026-03-07

---

**Moka caches accept any key type implementing `Hash + Eq + Send + Sync + 'static`, and uniquely do not require `Clone`, enabling non-copyable structs and zero-cost abstractions.**

The `moka-rs/moka` repository provides high-performance concurrent caching for Rust applications. Understanding which Moka cache key types are supported is essential for architecting efficient lookup structures, as the library places specific—but minimal—trait bounds on generic key parameters.

## Core Trait Requirements for Moka Cache Keys

Moka’s `Cache`, `SegmentedCache`, and their async equivalents are generic over key type `K` with exactly four constraints. According to the moka-rs/moka source code, the core cache implementation in [`src/sync/cache.rs`](https://github.com/moka-rs/moka/blob/main/src/sync/cache.rs) enforces `K: Hash + Eq + Send + Sync + 'static` on the generic `impl` for `Cache<K, V, S>` at lines 88-91.

The builder API applies identical constraints. In [`src/sync/builder.rs`](https://github.com/moka-rs/moka/blob/main/src/sync/builder.rs), lines 66-69, the `CacheBuilder` requires `K: Eq + Hash + Send + Sync + 'static` when constructing new cache instances.

These bounds ensure keys support:

- **Hashing** — For O(1) bucket lookups via the `Hash` trait
- **Equality comparison** — For key matching via `Eq` (which implies `PartialEq`)
- **Thread safety** — For concurrent access across threads via `Send + Sync`
- **Static lifetime** — For owned data safe to share without borrowing via `'static`

## Clone Is Not Required

Unlike standard Rust collections such as `HashMap`, Moka explicitly does **not** require keys to implement `Clone`. This architectural decision supports non-copyable types and eliminates unnecessary memory overhead when storing large or opaque keys.

The repository contains compile-time tests verifying this behavior. In [`tests/compile_tests/default/clone/sync_cache_clone.rs`](https://github.com/moka-rs/moka/blob/main/tests/compile_tests/default/clone/sync_cache_clone.rs) (lines 18-22) and [`tests/compile_tests/future/clone/future_cache_clone.rs`](https://github.com/moka-rs/moka/blob/main/tests/compile_tests/future/clone/future_cache_clone.rs) (lines 19-23), the test suite confirms that custom structs lacking `Clone` compile successfully as cache keys.

## Practical Examples of Supported Key Types

The following examples demonstrate valid key patterns for `moka::sync::Cache` and `moka::future::Cache`.

### Primitive Types

Standard primitives like `i32`, `u64`, and `String` satisfy all trait bounds automatically.

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

let cache: Cache<i32, String> = Cache::new(100);
cache.insert(1, "one".to_string());
assert_eq!(cache.get(&1), Some("one".to_string()));

```

### Custom Structs Without Clone

Define `Hash` and `Eq` manually or via derive macros. The example below uses a struct that explicitly does not implement `Clone`, matching the compile-test pattern from [`tests/compile_tests/default/clone/sync_cache_clone.rs`](https://github.com/moka-rs/moka/blob/main/tests/compile_tests/default/clone/sync_cache_clone.rs).

```rust
use std::hash::{Hash, Hasher};
use moka::sync::Cache;

#[derive(Eq)]
struct MyKey(i32);

impl PartialEq for MyKey {
    fn eq(&self, other: &Self) -> bool { self.0 == other.0 }
}

impl Hash for MyKey {
    fn hash<H: Hasher>(&self, state: &mut H) { self.0.hash(state); }
}

// Note: MyKey does NOT implement Clone
let cache: Cache<MyKey, String> = Cache::new(10);
cache.insert(MyKey(42), "answer".to_string());
assert_eq!(cache.get(&MyKey(42)), Some("answer".to_string()));

```

### Reference-Counted Wrappers

Types like `Arc<T>` work efficiently as keys when `T` implements the required traits, enabling shared ownership patterns without cloning underlying data.

### Custom Hashers

Supply a custom `BuildHasher` implementation via the builder API when specific hashing algorithms are required. The key type constraints remain unchanged regardless of hasher selection.

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

let hasher = RandomState::new();
let cache: Cache<u64, String, _> = Cache::builder()
    .max_capacity(50)
    .build_with_hasher(hasher);
    
cache.insert(7, "seven".to_string());
assert_eq!(cache.get(&7), Some("seven".to_string()));

```

## Async Cache Compatibility

The async cache implementations mirror the sync requirements exactly. In [`src/future/cache.rs`](https://github.com/moka-rs/moka/blob/main/src/future/cache.rs) and [`src/future/builder.rs`](https://github.com/moka-rs/moka/blob/main/src/future/builder.rs), the `future::Cache` and `future::CacheBuilder` enforce identical `K: Hash + Eq + Send + Sync + 'static` bounds. This parity ensures key types are portable between synchronous and asynchronous cache variants without modification.

## Summary

- Moka cache key types must implement `Hash + Eq + Send + Sync + 'static` as defined in [`src/sync/cache.rs`](https://github.com/moka-rs/moka/blob/main/src/sync/cache.rs) and [`src/sync/builder.rs`](https://github.com/moka-rs/moka/blob/main/src/sync/builder.rs)
- The `Clone` trait is **not** required, verified by compile-time tests in `tests/compile_tests/*/clone/*.rs`
- Primitive types, custom structs, and `Arc<T>` wrappers are all valid key candidates
- Async caches (`future::Cache`) apply identical trait constraints to their synchronous counterparts
- Custom hashers can be specified without altering key type requirements

## Frequently Asked Questions

### Do Moka cache keys need to implement Clone?

No. Moka explicitly designs against requiring `Clone` for keys. The source code includes compile-time tests in [`tests/compile_tests/default/clone/sync_cache_clone.rs`](https://github.com/moka-rs/moka/blob/main/tests/compile_tests/default/clone/sync_cache_clone.rs) and [`tests/compile_tests/future/clone/future_cache_clone.rs`](https://github.com/moka-rs/moka/blob/main/tests/compile_tests/future/clone/future_cache_clone.rs) that verify non-cloneable structs work correctly as cache keys.

### Can I use String as a key in Moka?

Yes. `String` implements `Hash`, `Eq`, `Send`, `Sync`, and `'static`, making it a fully supported key type without additional configuration or wrapper types.

### What hash algorithm does Moka use by default?

Moka uses `std::collections::hash_map::RandomState` (SipHash) by default for DOS resistance. You can override this with any `BuildHasher` implementation, such as `ahash::RandomState`, via `Cache::builder().build_with_hasher()` while maintaining the same key type constraints.

### Are tuples supported as Moka cache keys?

Yes. Tuples containing types that implement `Hash` and `Eq` (such as `(i32, String)` or `(u64, u64)`) automatically implement these traits themselves and are valid Moka cache key types.