# Moka Integration with async-std: A Complete Runtime Guide

> Integrate Moka's async cache with async-std easily. Learn how to leverage runtime-agnostic Futures for seamless caching in your Rust applications.

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

---

**Moka's asynchronous cache works seamlessly with async-std by enabling the `future` feature, which provides runtime-agnostic `Future` implementations compatible with any async executor.**

The moka-rs/moka crate provides high-performance, concurrent caching for Rust applications, and integrating Moka with async-std requires only the `future` feature flag to unlock async cache operations. This integration leverages the standard `std::future::Future` trait to ensure compatibility without runtime-specific dependencies.

## How Moka Supports async-std

Moka's async support is implemented in the `future` module, available when the **`future`** crate feature is enabled. Unlike some async libraries that hardcode runtime dependencies, Moka's cache is runtime-agnostic—it returns `impl Future` types that any executor can drive, including async-std's task scheduler.

### Enabling the `future` Feature

To use Moka with async-std, activate the feature in [`Cargo.toml`](https://github.com/moka-rs/moka/blob/main/Cargo.toml):

```toml
[dependencies]
moka = { version = "0.12", features = ["future"] }
async-std = { version = "1", features = ["attributes"] }

```

This feature flag pulls in optional dependencies (`async-lock`, `event-listener`, `futures-util`) and compiles the [`src/future/cache.rs`](https://github.com/moka-rs/moka/blob/main/src/future/cache.rs) module, which contains the async-aware cache implementation.

### Runtime-Agnostic Architecture

In [`src/future/cache.rs`](https://github.com/moka-rs/moka/blob/main/src/future/cache.rs), the `Cache` type implements `Send` (via `unsafe impl<K, V, S> Send for Cache` at line 641) and `Sync`, allowing safe sharing across async-std tasks. All async methods—including `insert`, `get`, and `invalidate`—return futures that are `Send + Sync`, satisfying async-std's task requirements without additional synchronization primitives.

As documented in the repository's [`README.md`](https://github.com/moka-rs/moka/blob/main/README.md), the `future` feature must be specified to use the cache under async runtimes such as `tokio` or `async-std`.

## Code Examples for async-std Integration

### Basic async-std Usage with `#[async_std::main]`

The simplest integration uses async-std's main macro to run cache operations directly. This pattern is documented in [`MIGRATION-GUIDE.md`](https://github.com/moka-rs/moka/blob/main/MIGRATION-GUIDE.md) (lines 136-166):

```rust
use std::sync::Arc;
use moka::future::Cache;

#[async_std::main]
async fn main() {
    // Create a future-aware cache that can hold 10_000 entries.
    let cache = Arc::new(Cache::new(10_000));

    // Insert a value asynchronously.
    cache.insert("hello", "world".to_owned()).await;

    // Retrieve it later.
    if let Some(v) = cache.get(&"hello").await {
        println!("Got: {v}");
    }
}

```

### Blocking from Synchronous Code with `block_on`

When calling Moka from synchronous contexts within an async-std application, use `async_std::task::block_on` to drive the futures:

```rust
use std::sync::Arc;
use async_std::task;
use moka::future::Cache;

fn main() {
    let cache = Arc::new(Cache::new(100));

    // Spawn a native OS thread that inserts a value.
    let cache_cloned = Arc::clone(&cache);
    std::thread::spawn(move || {
        // `block_on` drives the future on async-std's executor.
        task::block_on(cache_cloned.insert(42, "answer".to_owned()));
    })
    .join()
    .unwrap();

    // Verify from the normal thread (still uses block_on).
    let value = task::block_on(cache.get(&42));
    assert_eq!(value, Some("answer".to_owned()));
}

```

This approach, identical to the block-on example in [`MIGRATION-GUIDE.md`](https://github.com/moka-rs/moka/blob/main/MIGRATION-GUIDE.md), allows synchronous initialization code to populate the cache before spawning async tasks.

### Concurrent Access Across Multiple Tasks

Because `Cache` is both `Send` and `Sync`, you can share it across many concurrent async-std tasks using `Arc`:

```rust
use async_std::task;
use std::sync::Arc;
use moka::future::Cache;

#[async_std::main]
async fn main() {
    const N: usize = 8;
    let cache = Arc::new(Cache::new(1_000));

    // Launch several async tasks that concurrently insert entries.
    let mut handles = Vec::new();
    for i in 0..N {
        let c = Arc::clone(&cache);
        handles.push(task::spawn(async move {
            c.insert(i, format!("value-{i}")).await;
        }));
    }

    // Wait for all tasks to finish.
    for h in handles {
        h.await;
    }

    // All entries are now present.
    for i in 0..N {
        assert_eq!(cache.get(&i).await, Some(format!("value-{i}")));
    }
}

```

Each task receives a cloned `Arc<Cache>`, enabling cheap, lock-free sharing of the cache state across async-std's task scheduler.

## Key Source Files and Implementation Details

Understanding these files clarifies how Moka achieves async-std compatibility:

- **[`Cargo.toml`](https://github.com/moka-rs/moka/blob/main/Cargo.toml)** – Defines the `future` feature flag that enables async cache support and pulls in required dependencies (`async-lock`, `event-listener`, `futures-util`).
- **[`src/future/cache.rs`](https://github.com/moka-rs/moka/blob/main/src/future/cache.rs)** – Contains the core `Cache` implementation, including the `Send` trait implementation (line 641) that guarantees thread safety across async-std tasks.
- **[`MIGRATION-GUIDE.md`](https://github.com/moka-rs/moka/blob/main/MIGRATION-GUIDE.md)** – Provides concrete async-std usage patterns, including the `async_std::task::block_on` snippet and `#[async_std::main]` examples.
- **[`README.md`](https://github.com/moka-rs/moka/blob/main/README.md)** – Documents supported runtimes (Tokio, async-std, Actix-rt) and explains that the `future` feature is required for async runtime integration.

## Summary

- Enable the **`future`** feature in [`Cargo.toml`](https://github.com/moka-rs/moka/blob/main/Cargo.toml) to compile Moka's async cache module.
- Use **`moka::future::Cache`** for all async operations; it returns standard `Future` types compatible with async-std.
- The cache implements **`Send + Sync`**, allowing safe sharing across `async_std::task::spawn` without additional synchronization.
- From synchronous code, use **`async_std::task::block_on`** to drive cache futures on async-std's executor.
- No runtime-specific code is required in [`src/future/cache.rs`](https://github.com/moka-rs/moka/blob/main/src/future/cache.rs), making the integration runtime-agnostic.

## Frequently Asked Questions

### Does Moka require Tokio to work with async-std?

No. According to the moka-rs/moka source code, the cache is runtime-agnostic. When the `future` feature is enabled, the cache works with any executor implementing `std::future::Future`, including async-std, Tokio, or Actix-rt. The [`README.md`](https://github.com/moka-rs/moka/blob/main/README.md) explicitly lists async-std as a supported runtime.

### How do I enable async support in Moka?

Add `features = ["future"]` to your [`Cargo.toml`](https://github.com/moka-rs/moka/blob/main/Cargo.toml) dependency declaration for `moka`. This activates the `future` module in [`src/future/cache.rs`](https://github.com/moka-rs/moka/blob/main/src/future/cache.rs) and pulls in necessary async dependencies (`async-lock`, `event-listener`, `futures-util`) without binding to a specific runtime.

### Is Moka's async cache thread-safe for async-std tasks?

Yes. The `Cache` type in [`src/future/cache.rs`](https://github.com/moka-rs/moka/blob/main/src/future/cache.rs) implements both `Send` and `Sync` (see the `unsafe impl` block at line 641), meaning it can safely be shared between async-std tasks using `Arc` and accessed concurrently without data races.

### Can I use Moka from synchronous code when using async-std?

Yes. Use `async_std::task::block_on` to execute cache operations from synchronous contexts. As shown in [`MIGRATION-GUIDE.md`](https://github.com/moka-rs/moka/blob/main/MIGRATION-GUIDE.md), this pattern allows you to bridge sync and async code when pre-populating the cache or accessing it from non-async threads.