Client Pool
The ClientPool keeps a configurable number of MixnetClient instances pre-connected in a background loop, so callers don't pay the gateway handshake, key generation, and topology fetch cost on the hot path.
How it works
- Create the pool with a target reserve size:
ClientPool::new(5). - Start the background loop:
pool.start(). It immediately begins connecting clients. - Pop a client when needed:
pool.get_mixnet_client()returnsSome(client)orNoneif the pool is empty. - Use the client normally: send messages, open streams.
- Disconnect the client when done. The background loop notices the pool is below reserve and creates a replacement.
Clients are consumed, not returned. The pool creates new ones to maintain the reserve. If the pool is empty, you can fall back to MixnetClient::connect_new() (slower, but keeps things working).
The NymProxyClient (TcpProxy) uses a ClientPool internally: one client per incoming TCP connection.
Quick example
use nym_sdk::client_pool::ClientPool;
use nym_network_defaults::setup_env;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
nym_bin_common::logging::setup_tracing_logger();
// Load mainnet network defaults into env vars (required by ClientPool)
setup_env(None::<String>);
let pool = ClientPool::new(5); // maintain 5 clients in reserve
let pool_clone = pool.clone();
tokio::spawn(async move { pool_clone.start().await });
// Get a client when needed
if let Some(client) = pool.get_mixnet_client().await {
println!("Got client: {}", client.nym_address());
client.disconnect().await;
}
pool.disconnect_pool().await;
Ok(())
}Further reading
- Tutorial: Handle bursty traffic: step-by-step guide covering pool creation, burst handling, and fallback logic
- API reference on docs.rs (opens in a new tab): type details, method signatures, and architecture docs
- Example source on GitHub (opens in a new tab): complete working example