Join us at MongoDB.local London on 7 May to unlock new possibilities for your data. Use WEB50 to save 50%.
Register now >
Docs Menu
Docs Home
/ /

Customize Server Selection

All MongoDB drivers follow a defined algorithm when selecting a server to read or write from. The MongoDB Rust Driver lets you customize this algorithm to choose a server that works best for your application.

You can influence server selection in the following ways:

  • Use a read preference to describe suitable servers in a standardized way, such as primary, secondary, or nearest with tag sets and max staleness.

  • Provide a custom predicate via SelectionCriteria::Predicate to apply your own logic when filtering suitable servers.

Important

Customizing the server-selection algorithm can have unintended consequences, such as degraded read or write performance.

When the Rust driver executes an operation with custom selection criteria, it performs the following steps, in order, to select a MongoDB deployment:

  1. Choose eligible servers: From the list of known servers, the driver selects servers that match the active SelectionCriteria, either those matching a read preference or those for which a custom predicate returns true.

  2. Apply latency window: The driver applies the local_threshold setting to the list of eligible servers, filtering any server whose average round-trip time is outside the configured window of the fastest eligible server.

  3. Random selection: The driver randomly selects a server from those remaining in the latency window and executes the operation against this server.

When the Rust driver executes a write operation, it begins by selecting all writable servers, not just those that match the active read preference. The remaining steps are identical.

To learn more about the default server-selection algorithm, see Server Selection Algorithm in the MongoDB Server manual.

The Rust driver represents server-selection rules with the SelectionCriteria enum, as shown in the following example:

pub enum SelectionCriteria {
ReadPreference(ReadPreference),
Predicate(Predicate),
}

For any given operation, you use either SelectionCriteria::ReadPreference or SelectionCriteria::Predicate, not both:

  • ReadPreference: Describes suitable servers based on server type, tag sets, and max staleness, following the standard MongoDB read preference rules.

  • Predicate: Enables you to provide custom logic for cases that ReadPreference cannot express, such as preferring servers based on hostname patterns or other custom criteria.

A predicate is any closure that accepts a ServerInfo reference and returns true, indicating server suitability. The driver defines this as the type alias Predicate, shown in the following code:

pub type Predicate = Arc<dyn Send + Sync + Fn(&ServerInfo) -> bool>;

A server is considered suitable when your predicate returns true for that server's ServerInfo value. The ServerInfo type exposes information about the server such as the address, type, and other monitoring metadata.

If you use a sharded cluster with multiple mongos servers, you may prefer deployments running on localhost. Operations against these deployments have lower latency and higher throughput. This example shows how to customize the server-selection algorithm to consider only servers running on localhost.

The predicate function must meet the following criteria:

  • Accepts a reference to a ServerInfo object as a parameter

  • Returns a boolean indicating whether the server is suitable for selection

  • Does not create or modify any ServerInfo objects

The following example defines a predicate that prefers servers whose host address is localhost:

let prefer_localhost = Arc::new(|server_info: &ServerInfo| {
matches!(
server_info.address(),
ServerAddress::Tcp { host, .. } if host == "localhost"
)
});

If your predicate returns false for every available server, the driver cannot select a server. In this case, the operation fails and returns a server selection timeout error indicating that none of the available servers are suitable for the specified criteria.

To avoid this outcome, ensure your predicate matches at least one server under normal conditions, or handles server selection errors in your application code and retries with a less restrictive SelectionCriteria if necessary.

To use your predicate for server selection, pass it to the selection_criteria option when you create the client. Select the :guilabel:Asynchronous or :guilabel:Synchronous tab to see the corresponding code for each runtime:

let prefer_localhost = Arc::new(|server_info: &ServerInfo| {
matches!(
server_info.address(),
ServerAddress::Tcp { host, .. } if host == "localhost"
)
});
let options = ClientOptions::builder()
.hosts(vec![ServerAddress::Tcp {
host: "<hostname>".to_string(),
port: Some(27017),
}])
.selection_criteria(SelectionCriteria::Predicate(prefer_localhost))
.build();
let client = Client::with_options(options)?;
let mut options = ClientOptions::parse(
"mongodb://<db_username>:<db_password>@<hostname>:<port>",
)
.await?;
let prefer_localhost = Arc::new(|server_info: &ServerInfo| {
matches!(
server_info.address(),
ServerAddress::Tcp { host, .. } if host == "localhost"
)
});
options.selection_criteria = Some(
SelectionCriteria::Predicate(prefer_localhost),
);
let client = Client::with_options(options)?;

For more information about customizing the Rust driver's server-selection algorithm, see the following API documentation:

Back

Compress Network Traffic

On this page