Skip to main content
State allows you to share data across all handlers in your application. This is commonly used for database connection pools, configuration, caches, and other shared resources.

Creating state

State must implement Clone to be shared across handlers:

Using with_state

Provide state to your router using the with_state method:
1

Define your state type

Create a struct that implements Clone:
2

Create handlers that use State

Use the State extractor in your handlers:
3

Apply state to your router

Call with_state on your router:

Shared mutable state

Since state is cloned for each request, use Arc<Mutex<_>> or Arc<RwLock<_>> for mutable state:
Don’t hold a std::sync::Mutex across .await points. Use tokio::sync::Mutex instead.

Real-world example

A complete example with database connection pool:

Combining routers with state

When combining routers, they must have the same state type:

Substates with FromRef

Extract parts of your state using the FromRef trait:
You can also use #[derive(FromRef)] to automatically implement FromRef for each field:

State in middleware

Access state in middleware using from_fn_with_state:

Next steps

Middleware

Learn how to use middleware with state

Extractors

See all available extractors including State