Developers
Client Pool Module

Client Pool

The ClientPool maintains a configurable number of connected ephemeral MixnetClient instances, ready for immediate use. This eliminates the connection latency that comes with creating a new client on each request: the gateway handshake, key generation, and topology fetch all happen ahead of time.

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, etc.
  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() -> anyhow::Result<()> {
    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