Install the posthog-rs crate by adding it to your Cargo.toml.
[dependencies]
posthog-rs = "0.3.5"
Next, set up the client with your PostHog project key.
let client = posthog_rs::client(env!("<ph_project_api_key>"));
Our Rust SDK supports both blocking and async clients. The async client is the default and is recommended for most use cases.
If you need to use a synchronous client instead – like we do in our CLI –, you can opt into it by disabling the asynchronous feature on your Cargo.toml file.
[dependencies]
posthog-rs = { version = "0.3.5", default-features = false }
In blocking mode, calls to capture and related methods will block until the PostHog event capture API returns – generally this is on the order of tens of milliseconds, but you may want to thread::spawn a background thread when you send an event.
You can send custom events using capture:
let mut event = Event::new("user_signed_up", "distinct_id_of_the_user");
client.capture(event).unwrap();
Tip: We recommend using a [object] [verb] format for your event names, where [object] is the entity that the behavior relates to, and [verb] is the behavior itself. For example, project created, user signed up, or invite sent.
Optionally, you can include additional information with the event by including a properties object:
let mut event = Event::new("user_signed_up", "distinct_id_of_the_user");
event.insert_prop("login_type", "email").unwrap();
event.insert_prop("is_free_trial", true).unwrap();
client.capture(event).unwrap();
To capture multiple events at once, use batch():
let event1 = posthog_rs::Event::new("event 1", "distinct_id_of_user_A");
let event2 = posthog_rs::Event::new("event 2", "distinct_id_of_user_B");
client.capture_batch(vec![event1, event2]).unwrap();
PostHog's feature flags enable you to safely deploy and roll back new features as well as target specific users and groups with them.
let is_enabled = client.is_feature_enabled(
"flag-key".to_string(),
"distinct_id_of_your_user".to_string(),
None, None, None
).await.unwrap();
if is_enabled {
// Do something differently for this user
}
use posthog_rs::FlagValue;
match client.get_feature_flag(
"flag-key".to_string(),
"distinct_id_of_your_user".to_string(),
None, None, None
).await.unwrap() {
Some(FlagValue::String(variant)) => {
if variant == "variant-key" {
// Do something for this variant
}
}
Some(FlagValue::Boolean(enabled)) => {
// Handle boolean flag
}
None => {
// Flag not found or disabled
}
}
let (flags, payloads) = client.get_feature_flags(
"distinct_id_of_your_user".to_string(),
None, None, None
).await.unwrap();
for (key, value) in flags {
println!("Flag {}: {:?}", key, value);
}
let payload = client.get_feature_flag_payload(
"flag-key".to_string(),
"distinct_id_of_your_user".to_string()
).await.unwrap();
if let Some(data) = payload {
println!("Payload: {}", data);
}
use std::collections::HashMap;
use serde_json::json;
let mut person_props = HashMap::new();
person_props.insert("plan".to_string(), json!("enterprise"));
person_props.insert("country".to_string(), json!("US"));
let flag = client.get_feature_flag(
"premium-feature".to_string(),
"distinct_id_of_your_user".to_string(),
None,
Some(person_props),
None
).await.unwrap();
For B2B applications with group-based flags:
use std::collections::HashMap;
use serde_json::json;
let mut groups = HashMap::new();
groups.insert("company".to_string(), "company-123".to_string());
let mut group_props = HashMap::new();
let mut company_props = HashMap::new();
company_props.insert("size".to_string(), json!(500));
group_props.insert("company".to_string(), company_props);
let flag = client.get_feature_flag(
"b2b-feature".to_string(),
"distinct_id_of_your_user".to_string(),
Some(groups),
None,
Some(group_props)
).await.unwrap();
For improved performance, you can evaluate feature flags locally by enabling local evaluation. This caches flag definitions and evaluates them without making API requests for each flag check.
To enable local evaluation, you need a personal API key and to configure the client:
use posthog_rs::ClientOptionsBuilder;
let options = ClientOptionsBuilder::default()
.api_key("your-project-api-key")
.personal_api_key("your-personal-api-key")
.enable_local_evaluation(true)
.poll_interval_seconds(30) // Optional, defaults to 30
.build()
.unwrap();
let client = posthog_rs::client(options).await;
When local evaluation is enabled, flag definitions are fetched on initialization and periodically refreshed in the background. Flag evaluation then happens locally without network requests, providing 100-1000x faster performance.
Note: Local evaluation requires providing any person properties, groups, or group properties needed to evaluate the flag's release conditions, since PostHog can't fetch these automatically without a server request.