Skip to main content
Execution profiles are a powerful feature that lets you group configurable options for CQL statement execution. They enable you to define different workloads and switch between them conveniently on a single session.

Overview

An execution profile is an immutable set of configuration options that control how queries are executed. You can create multiple profiles for different workloads and attach them to sessions or individual statements. There are two main classes of objects:
  • ExecutionProfile: An immutable set of execution settings
  • ExecutionProfileHandle: A handle that points to an ExecutionProfile and can be remapped

Configurable Options

Execution profiles can configure the following options:
  • Request timeout: Client-side timeout for statement execution
  • Consistency level: Default consistency for read/write operations
  • Serial consistency: Default serial consistency for LWT operations
  • Load balancing policy: Policy for selecting nodes to contact
  • Retry policy: Policy for deciding when to retry failed requests
  • Speculative execution policy: Policy for sending speculative requests

Creating a Profile

Use the builder pattern to create an execution profile:
use scylla::client::execution_profile::ExecutionProfile;
use scylla::statement::Consistency;
use std::time::Duration;

let profile = ExecutionProfile::builder()
    .consistency(Consistency::LocalQuorum)
    .request_timeout(Some(Duration::from_secs(30)))
    .build();

Attaching to Session

You can set a default execution profile for a session:
use scylla::client::session_builder::SessionBuilder;

let handle = profile.into_handle();

let session = SessionBuilder::new()
    .known_node("127.0.0.1:9042")
    .default_execution_profile_handle(handle)
    .build()
    .await?;

Attaching to Statements

You can also attach profiles to individual statements:
use scylla::statement::unprepared::Statement;

let handle = profile.into_handle();

let mut query = Statement::from("SELECT * FROM keyspace.table");
query.set_execution_profile_handle(Some(handle));

Profile Handles

Handles provide a level of indirection that enables powerful remapping capabilities:
let profile1 = ExecutionProfile::builder()
    .consistency(Consistency::One)
    .build();

let profile2 = ExecutionProfile::builder()
    .consistency(Consistency::Two)
    .build();

let mut handle1 = profile1.clone().into_handle();
let mut handle2 = profile2.clone().into_handle();

// Multiple statements can share the same handle
query1.set_execution_profile_handle(Some(handle1.clone()));
query2.set_execution_profile_handle(Some(handle1.clone()));

// Remap handle1 to profile2
handle1.map_to_another_profile(profile2);
// Now both query1 and query2 use profile2

Building from Existing Profile

You can create a new profile based on an existing one:
let base_profile = ExecutionProfile::builder()
    .request_timeout(Some(Duration::from_secs(30)))
    .build();

let derived_profile = base_profile.to_builder()
    .consistency(Consistency::All)
    .build();

Default Values

If not specified, execution profiles use these defaults:
  • Consistency: LocalQuorum
  • Serial consistency: LocalSerial
  • Request timeout: 30 seconds
  • Load balancing policy: DefaultPolicy
  • Retry policy: DefaultRetryPolicy
  • Speculative execution policy: None

Best Practices

  • Create profiles for different workloads (e.g., latency-sensitive reads, batch writes)
  • Use handles to enable dynamic workload switching
  • Set reasonable timeouts to prevent hanging requests
  • Choose consistency levels appropriate for your use case
  • Consider using speculative execution for read-heavy latency-sensitive workloads

Next Steps

Build docs developers (and LLMs) love