> ## Documentation Index
> Fetch the complete documentation index at: https://launchdarkly.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Rust SDK 2.x to 3.0 migration guide

<View title="Developer" />

<View title="Federal docs" />

<View title="EU docs" />

This topic explains how to adapt code that currently uses a 2.x version of the [Rust server-side SDK](/docs/sdk/server-side/rust) to use version 3.0 or later.

**Version 3.0 includes breaking changes**. The most significant changes involve the HTTP transport layer, TLS/crypto feature flags, and some API refinements.

To learn more about the latest release, visit the [SDK's GitHub repository](https://github.com/launchdarkly/rust-server-sdk/releases).

## Understanding changes to Cargo features

The most impactful change in version 3.0 is the restructuring of Cargo feature flags. The default features have changed, and several new features have been introduced to give you more control over TLS backends and cryptographic implementations.

Here is a summary of the feature flag changes:

<table>
  <thead>
    <tr>
      <th>v2 Feature</th>
      <th>v3 Feature</th>
      <th>Notes</th>
    </tr>
  </thead>

  <tbody>
    <tr>
      <td><code>rustls</code> (default)</td>
      <td><code>hyper-rustls-native-roots</code> (default)</td>
      <td>Renamed to clarify TLS backend and root certificate source</td>
    </tr>

    <tr>
      <td>N/A</td>
      <td><code>hyper-rustls-webpki-roots</code></td>
      <td>New option: uses <code>rustls</code> with bundled WebPKI root certificates</td>
    </tr>

    <tr>
      <td>N/A</td>
      <td><code>native-tls</code></td>
      <td>New option: uses the platform's native TLS implementation</td>
    </tr>

    <tr>
      <td>N/A</td>
      <td><code>hyper</code></td>
      <td>Base HTTP feature for hyper-based transports</td>
    </tr>

    <tr>
      <td>N/A</td>
      <td><code>crypto-aws-lc-rs</code> (default)</td>
      <td>Cryptographic backend, previously always included</td>
    </tr>

    <tr>
      <td>N/A</td>
      <td><code>crypto-openssl</code></td>
      <td>New alternative: uses OpenSSL for cryptographic operations</td>
    </tr>

    <tr>
      <td><code>event-compression</code> (opt-in)</td>
      <td><code>event-compression</code> (default)</td>
      <td>Now enabled by default</td>
    </tr>
  </tbody>
</table>

<Warning>
  **Feature flag changes may affect compilation**

  If you previously relied on default features, your `Cargo.toml` may need updates. The renamed and restructured features mean that a version bump only may not compile without adjusting your feature configuration.
</Warning>

If you were using default features in v2.x, the defaults in v3.0 provide equivalent behavior. No changes to your `Cargo.toml` are needed in this case:

<CodeGroup>
  ```toml title="2.x Cargo.toml (default features)" lines wrap theme={null}
  [dependencies]
  launchdarkly-server-sdk = "2"
  ```

  ```toml title="3.0 Cargo.toml (default features)" lines wrap theme={null}
  [dependencies]
  launchdarkly-server-sdk = "3"
  ```
</CodeGroup>

If you were explicitly enabling the `rustls` feature, update to the new feature name:

<CodeGroup>
  ```toml title="2.x Cargo.toml" lines wrap theme={null}
  [dependencies]
  launchdarkly-server-sdk = { version = "2", default-features = false, features = ["rustls"] }
  ```

  ```toml title="3.0 Cargo.toml" lines wrap theme={null}
  [dependencies]
  launchdarkly-server-sdk = { version = "3", default-features = false, features = ["hyper-rustls-native-roots", "crypto-aws-lc-rs"] }
  ```
</CodeGroup>

You can also use alternative TLS or crypto backends:

<CodeGroup>
  ```toml title="WebPKI root certificates" lines wrap theme={null}
  [dependencies]
  launchdarkly-server-sdk = { version = "3", default-features = false, features = ["hyper-rustls-webpki-roots", "crypto-aws-lc-rs"] }
  ```

  ```toml title="native TLS backend" lines wrap theme={null}
  [dependencies]
  launchdarkly-server-sdk = { version = "3", default-features = false, features = ["native-tls", "crypto-aws-lc-rs"] }
  ```

  ```toml title="OpenSSL" lines wrap theme={null}
  [dependencies]
  launchdarkly-server-sdk = { version = "3", default-features = false, features = ["hyper-rustls-native-roots", "crypto-openssl"] }
  ```
</CodeGroup>

## Understanding the new transport layer

Version 3.0 introduces a new `launchdarkly-sdk-transport` crate that provides the `HttpTransport` trait. This trait abstracts the HTTP transport layer, replacing the previous approach of directly using hyper connectors.

The built-in implementation is `HyperTransport`. This is used by default when you enable any of the hyper-based features, including `hyper-rustls-native-roots`, `hyper-rustls-webpki-roots`, or `native-tls`.

If you were using the SDK with default settings and not customizing the HTTP connector, this change is transparent. The SDK automatically creates the appropriate `HyperTransport` based on your enabled features.

If you were providing a custom hyper connector, you now need to wrap it in a `HyperTransport` or implement the `HttpTransport` trait directly:

<CodeGroup>
  ```rust title="2.x syntax" lines wrap theme={null}
  use launchdarkly_server_sdk::ConfigBuilder;
  use hyper_rustls::HttpsConnectorBuilder;

  let connector = HttpsConnectorBuilder::new()
      .with_native_roots()
      .https_or_http()
      .enable_http1()
      .build();

  let config = ConfigBuilder::new("sdk-key")
      .datasource_with_connector(&connector)
      .build();
  ```

  ```rust title="3.0 syntax" expandable lines wrap theme={null}
  use launchdarkly_server_sdk::ConfigBuilder;
  use launchdarkly_sdk_transport::HyperTransport;
  use hyper_rustls::HttpsConnectorBuilder;

  let connector = HttpsConnectorBuilder::new()
      .with_native_roots()
      .unwrap()
      .https_or_http()
      .enable_http1()
      .build();

  let transport = HyperTransport::new(connector);

  let config = ConfigBuilder::new("sdk-key")
      .datasource_with_transport(&transport)
      .build();
  ```
</CodeGroup>

## Understanding changes to data source configuration

The streaming and polling data source builders now use the `HttpTransport` trait instead of a generic connector type parameter.

The type signatures have changed:

* `StreamingDataSourceBuilder<C>` is now `StreamingDataSourceBuilder<T: HttpTransport>`
* `PollingDataSourceBuilder<C>` is now `PollingDataSourceBuilder<T: HttpTransport>`

The method for providing a custom transport has also been renamed:

* `.https_connector(connector)` is now `.transport(transport)`

Here is an example:

<CodeGroup>
  ```rust title="2.x syntax" lines wrap theme={null}
  use launchdarkly_server_sdk::{ConfigBuilder, StreamingDataSourceBuilder};

  let builder = StreamingDataSourceBuilder::new()
      .https_connector(my_connector);

  let config = ConfigBuilder::new("sdk-key")
      .datasource(builder)
      .build();
  ```

  ```rust title="3.0 syntax" lines wrap theme={null}
  use launchdarkly_server_sdk::{ConfigBuilder, StreamingDataSourceBuilder};
  use launchdarkly_sdk_transport::HyperTransport;

  let transport = HyperTransport::new(my_connector);

  let builder = StreamingDataSourceBuilder::new()
      .transport(transport);

  let config = ConfigBuilder::new("sdk-key")
      .datasource(builder)
      .build();
  ```
</CodeGroup>

## Understanding changes to event processor configuration

The event processor builder now uses the `HttpTransport` trait instead of a generic connector type parameter.

The type signature has changed:

* `EventProcessorBuilder<C>` is now `EventProcessorBuilder<T: HttpTransport>`, with a default type parameter

The method for providing a custom transport has been renamed:

* `.https_connector(connector)` is now `.transport(transport)`

Additionally, `compress_events` now defaults to `true`, while it defaulted to `false` in v2. If you previously relied on the default of no compression, you need to explicitly disable it.

<Warning>
  **Event compression and the Relay Proxy**

  If you are using the [Relay Proxy](/docs/sdk/relay-proxy), we recommend disabling event compression by setting `.compress_events(false)`. Sending compressed events through the Relay Proxy causes unnecessary encoding, decoding, and re-encoding overhead.

  Additionally, Relay Proxy versions prior to v8.9.0 cannot receive compressed events. If you are using a Relay Proxy version older than v8.9.0, you must disable event compression or upgrade your Relay Proxy.
</Warning>

Here is an example:

<CodeGroup>
  ```rust title="2.x syntax" lines wrap theme={null}
  use launchdarkly_server_sdk::{ConfigBuilder, EventProcessorBuilder};

  let builder = EventProcessorBuilder::new()
      .https_connector(my_connector)
      .compress_events(true); // had to opt in

  let config = ConfigBuilder::new("sdk-key")
      .event_processor(builder)
      .build();
  ```

  ```rust title="3.0 syntax" lines wrap theme={null}
  use launchdarkly_server_sdk::{ConfigBuilder, EventProcessorBuilder};
  use launchdarkly_sdk_transport::HyperTransport;

  let transport = HyperTransport::new(my_connector);

  let builder = EventProcessorBuilder::new()
      .transport(transport);
      // compress_events is now true by default

  let config = ConfigBuilder::new("sdk-key")
      .event_processor(builder)
      .build();
  ```
</CodeGroup>

## Understanding changes to FlagDetailConfig

The `FlagDetailConfig` type has been updated. The `client_side_only()` method has been removed and replaced with a more flexible `flag_filter` method that accepts `FlagFilter` bitflags.

The new `FlagFilter` type supports:

* `FlagFilter::CLIENT` filters for flags available to client-side SDKs. It replaces `client_side_only()`.
* `FlagFilter::MOBILE` filters for flags available to mobile SDKs. This is a new filter.

You can combine filters using the bitwise `OR` operator.

Here is an example:

<CodeGroup>
  ```rust title="2.x syntax" lines wrap theme={null}
  use launchdarkly_server_sdk::FlagDetailConfig;

  // Filter for client-side flags only
  let config = FlagDetailConfig::new()
      .client_side_only();
  ```

  ```rust title="3.0 syntax" lines wrap theme={null}
  use launchdarkly_server_sdk::{FlagDetailConfig, FlagFilter};

  // Filter for client-side flags only
  let config = FlagDetailConfig::new()
      .flag_filter(FlagFilter::CLIENT);

  // Filter for mobile flags only
  let config = FlagDetailConfig::new()
      .flag_filter(FlagFilter::MOBILE);

  // Filter for both client-side and mobile flags
  let config = FlagDetailConfig::new()
      .flag_filter(FlagFilter::CLIENT | FlagFilter::MOBILE);
  ```
</CodeGroup>

## Understanding changes to `secure_mode_hash`

The `secure_mode_hash` method's return type has changed from `String` to `Result<String, String>`. This change reflects the fact that the cryptographic operation can fail.

Additionally, `secure_mode_hash` is now only available when either the `crypto-aws-lc-rs` or `crypto-openssl` feature is enabled.

Here is an example:

<CodeGroup>
  ```rust title="2.x syntax" lines wrap theme={null}
  use launchdarkly_server_sdk::Client;

  let hash: String = client.secure_mode_hash(&context);
  ```

  ```rust title="3.0 syntax" lines wrap theme={null}
  use launchdarkly_server_sdk::Client;

  // Now returns a Result
  match client.secure_mode_hash(&context) {
      Ok(hash) => println!("Hash: {}", hash),
      Err(e) => eprintln!("Failed to compute hash: {}", e),
  }
  ```
</CodeGroup>

## Understanding changes to the `EventProcessor` trait

If you have implemented a custom `EventProcessor`, you need to add a new required method: `flush_blocking`. This method performs a synchronous flush of pending events with a timeout.

The signature is:

<CodeGroup>
  ```rust title="Flush blocking" lines wrap theme={null}
  fn flush_blocking(&self, timeout: Duration) -> bool;
  ```
</CodeGroup>

The method should trigger a flush of events currently in the outbox and block until that flush completes or the timeout expires. It returns `true` if the flush completed successfully, or `false` if it timed out.

<Info>
  **Built-in implementations are already updated**

  If you are using the SDK's built-in event processor or `NullEventProcessor`, no changes are required. This only affects custom `EventProcessor` trait implementations.
</Info>
