Temporal Client - Rust SDK
A Temporal Client enables you to communicate with the Temporal Service. Communication with a Temporal Service lets you perform actions such as starting Workflow Executions, sending Signals to Workflow Executions, sending Queries to Workflow Executions, getting the results of a Workflow Execution, and terminating Workflow Executions.
This page shows you how to do the following using the Rust SDK:
- Connect to a development Temporal Service
- Connect to Temporal Cloud
- Start a Workflow Execution
- Get Workflow results
- Send Signals to Workflows
- Query Workflows
- Execute Updates
- Cancel Workflows
A Temporal Client cannot be initialized and used inside a Workflow. However, it is acceptable and common to use a Temporal Client inside an Activity to communicate with a Temporal Service.
Connect to a development Temporal Service
To connect to a Temporal Service running locally on the default port (7233):
use temporalio_client::{Client, ClientOptions, Connection, envconfig::LoadClientConfigProfileOptions};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Load configuration from environment variables or config file
let (conn_options, client_options) = ClientOptions::load_from_config(
LoadClientConfigProfileOptions::default()
)?;
// Create connection
let connection = Connection::connect(conn_options).await?;
// Create client
let client = Client::new(connection, client_options);
Ok(())
}
The SDK automatically loads configuration from:
- Environment variables (highest priority)
- Configuration file at path specified by
TEMPORAL_CONFIG_FILE - Default configuration file at
~/.config/temporalio/temporal.toml
For a list of all available environment variables and their defaults, refer to Environment Configuration.
Configure Client with Code
If you prefer to configure the client directly in code:
use temporalio_client::{Client, ClientOptions, WorkflowServiceStubsOptions};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Configure connection options
let conn_options = WorkflowServiceStubsOptions::new()
.target_url("localhost:7233".parse()?)
.build();
// Configure client options
let client_options = ClientOptions::new()
.namespace("default");
// Create connection and client
let connection = Connection::connect(conn_options).await?;
let client = Client::new(connection, client_options);
Ok(())
}
Connect to Temporal Cloud
To connect to Temporal Cloud, you need:
- Your Namespace and Account ID (in format
namespace.account-id) - Either an API Key or mTLS certificates
Connect with API Key
use temporalio_client::{Client, ClientOptions, WorkflowServiceStubsOptions};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let namespace = "your-namespace.abc123"; // Your namespace.account-id
let api_key = "your-api-key"; // Your Temporal Cloud API key
let conn_options = WorkflowServiceStubsOptions::new()
.target_url("your-namespace.abc123.tmprl.cloud:7233".parse()?)
.api_key(api_key.into())
.build();
let client_options = ClientOptions::new()
.namespace(namespace);
let connection = Connection::connect(conn_options).await?;
let client = Client::new(connection, client_options);
Ok(())
}
Connect with mTLS Certificates
use temporalio_client::{Client, ClientOptions, WorkflowServiceStubsOptions};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let namespace = "your-namespace.abc123";
let conn_options = WorkflowServiceStubsOptions::new()
.target_url("your-namespace.abc123.tmprl.cloud:7233".parse()?)
.client_cert_path("/path/to/client.pem".into())
.client_key_path("/path/to/client.key".into())
.build();
let client_options = ClientOptions::new()
.namespace(namespace);
let connection = Connection::connect(conn_options).await?;
let client = Client::new(connection, client_options);
Ok(())
}
Start a Workflow Execution
Use client.start_workflow() to start a Workflow Execution:
use temporalio_client::{Client, WorkflowOptions};
use std::time::Duration;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = /* ... setup ... */;
// Start a workflow
let handle = client.start_workflow(
GreetingWorkflow::run,
"World".to_string(),
WorkflowOptions::new("my-task-queue", "greeting-1")
.workflow_execution_timeout(Some(Duration::from_secs(3600)))
.build()
).await?;
println!("Started workflow: {}", handle.workflow_id());
Ok(())
}
Workflow Execution Options
Common Workflow Options:
use temporalio_client::WorkflowOptions;
use std::time::Duration;
let options = WorkflowOptions::new("my-task-queue", "workflow-id-123")
// Maximum time the Workflow can execute
.workflow_execution_timeout(Some(Duration::from_secs(3600)))
// Maximum time between Workflow Task starts
.workflow_run_timeout(Some(Duration::from_secs(1800)))
// Maximum time for a single Workflow Task
.workflow_task_timeout(Some(Duration::from_secs(10)))
// ID to retry with for idempotency
.workflow_id_reuse_policy(WorkflowIdReusePolicy::AllowDuplicate)
// Retry policy for Workflow retries
.retry_policy(Some(RetryPolicy { /* ... */ }))
// Memo data (not searchable)
.memo(/* ... */)
// Search attributes (searchable, queryable)
.search_attributes(/* ... */)
.build();
Get Workflow Results
Use the workflow handle to get results:
// Get handle from start_workflow or by workflow ID
let handle = client.get_workflow_handle::<GreetingWorkflow>("workflow-id");
// Wait for result (blocking until complete)
let result = handle.get_result::<String>(GetWorkflowResultOptions::default()).await?;
println!("Workflow result: {}", result);
// OR get result immediately if available
match handle.get_result::<String>(GetWorkflowResultOptions::default()).wait_timeout(Duration::from_secs(0)).await {
Ok(result) => println!("Result: {}", result),
Err(_) => println!("Workflow still running"),
}
Send Signals to Workflows
Send a Signal to a running Workflow:
use temporalio_client::SignalOptions;
let handle = client.get_workflow_handle::<MyWorkflow>("workflow-id");
// Send a signal
handle.signal(
MyWorkflow::my_signal,
"signal-value".to_string(),
SignalOptions::default(),
).await?;
Query Workflows
Query a running Workflow for its state:
use temporalio_client::QueryOptions;
let handle = client.get_workflow_handle::<MyWorkflow>("workflow-id");
// Execute a query
let status = handle.query(
MyWorkflow::get_status,
(),
QueryOptions::default(),
).await?;
println!("Workflow status: {}", status);
Execute Updates
Execute an Update on a running Workflow:
use temporalio_client::UpdateOptions;
let handle = client.get_workflow_handle::<MyWorkflow>("workflow-id");
// Execute an update synchronously
let result = handle.execute_update(
MyWorkflow::my_update,
42,
UpdateOptions::default(),
).await?;
println!("Update result: {:?}", result);
Asynchronous Updates
Start an update and get the result later:
use temporalio_client::{StartUpdateOptions, WorkflowUpdateWaitStage};
let handle = client.get_workflow_handle::<MyWorkflow>("workflow-id");
// Start update and wait only until accepted
let update_handle = handle.start_update(
MyWorkflow::my_update,
42,
StartUpdateOptions::builder()
.wait_for_stage(WorkflowUpdateWaitStage::Accepted)
.build()
).await?;
// Do other work...
// Get result when ready
let result = update_handle.get_result().await?;
Cancel Workflows
Request cancellation of a running Workflow:
use temporalio_client::CancelWorkflowOptions;
let handle = client.get_workflow_handle::<MyWorkflow>("workflow-id");
// Request cancellation (allows graceful shutdown)
handle.cancel(
CancelWorkflowOptions::builder()
.reason("User requested cancellation")
.build()
).await?;
The Workflow will receive the cancellation request via ctx.cancelled() and can clean up gracefully.
Terminate Workflows
Immediately terminate a Workflow (without allowing cleanup):
use temporalio_client::TerminateWorkflowOptions;
let handle = client.get_workflow_handle::<MyWorkflow>("workflow-id");
// Terminate immediately
handle.terminate(
TerminateWorkflowOptions::builder()
.reason("Emergency: forcing shutdown")
.build()
).await?;
Unlike cancellation, termination is immediate and the Workflow cannot handle it.
List Workflows
Query and list running Workflows:
use temporalio_client::ListWorkflowsOptions;
use futures_util::StreamExt;
let mut stream = client.list_workflows(
"WorkflowType = 'MyWorkflow'",
ListWorkflowsOptions::builder()
.limit(10)
.build()
);
while let Some(result) = stream.next().await {
let execution = result?;
println!("Workflow: {} ({})", execution.id(), execution.workflow_type());
}
Best Practices
- Reuse Client instances: Create one Client and share it across your application
- Load configuration from environment: Use environment variables or config files for deployment flexibility
- Handle errors gracefully: Always check for connection errors and handle them appropriately
- Use meaningful Workflow IDs: Make it easy to track and query Workflows
- Set appropriate timeouts: Prevent Workflows from running indefinitely
- Use Search Attributes: Make your Workflows discoverable with searchable metadata
For more information, see Environment Configuration and Visibility.