Developers
Client Pool Module

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

  1. Create the pool with a target reserve size: ClientPool::new(5).
  2. Start the background loop: pool.start(). It immediately begins connecting clients.
  3. Pop a client when needed: pool.get_mixnet_client() returns Some(client) or None if the pool is empty.
  4. Use the client normally: send messages, open streams.
  5. 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