> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/open-telemetry/opentelemetry-rust/llms.txt
> Use this file to discover all available pages before exploring further.

# Baggage

> Add custom attributes to context that propagate across service boundaries

## Overview

Baggage is a mechanism for propagating name-value pairs across service boundaries. It allows you to attach custom attributes to telemetry context that can be accessed by any service in the call chain.

<Warning>
  Baggage is not automatically added to spans, metrics, or logs. You must explicitly read baggage entries and add them to your telemetry.
</Warning>

## What is baggage?

Baggage is a set of key-value pairs that:

* Travels with the context across process boundaries
* Can be read and modified by any service
* Follows the [W3C Baggage](https://w3c.github.io/baggage) specification
* Has size and count limits for safety

### Limits

```rust theme={null}
const MAX_KEY_VALUE_PAIRS: usize = 64;
const MAX_LEN_OF_ALL_PAIRS: usize = 8192;
```

* **Maximum entries**: 64 key-value pairs
* **Maximum size**: 8192 bytes total

## Basic usage

### Creating baggage

```rust theme={null}
use opentelemetry::baggage::Baggage;

let mut baggage = Baggage::new();
baggage.insert("user.id", "12345");
baggage.insert("tenant.name", "acme-corp");
baggage.insert("feature.flag", "experimental");
```

### Reading baggage

```rust theme={null}
if let Some(user_id) = baggage.get("user.id") {
    println!("User ID: {}", user_id);
}
```

### Baggage with metadata

```rust theme={null}
use opentelemetry::baggage::{Baggage, BaggageMetadata};

let mut baggage = Baggage::new();
let metadata = BaggageMetadata::from("ttl=3600");
baggage.insert_with_metadata("session.id", "abc-123", metadata);

// Retrieve with metadata
if let Some((value, metadata)) = baggage.get_with_metadata("session.id") {
    println!("Session: {}, Metadata: {:?}", value, metadata);
}
```

## BaggageExt trait

The `BaggageExt` trait extends `Context` with baggage management:

```rust theme={null}
use opentelemetry::Context;
use opentelemetry::baggage::BaggageExt;

// Get baggage from context
let cx = Context::current();
let baggage = cx.baggage();

// Create context with baggage
let mut new_baggage = Baggage::new();
new_baggage.insert("request.id", "req-789");
let cx = cx.with_baggage(new_baggage);
```

## Propagation

Baggage automatically propagates when using the `BaggagePropagator`:

```rust theme={null}
use opentelemetry::global;
use opentelemetry::propagation::TextMapCompositePropagator;
use opentelemetry_sdk::propagation::{BaggagePropagator, TraceContextPropagator};

// Configure propagator to include baggage
let propagator = TextMapCompositePropagator::new(vec![
    Box::new(TraceContextPropagator::new()),
    Box::new(BaggagePropagator::new()),
]);

global::set_text_map_propagator(propagator);
```

## Complete example

### Service A (upstream)

```rust theme={null}
use opentelemetry::{
    baggage::{Baggage, BaggageExt},
    global,
    trace::{Tracer, TraceContextExt},
    Context, KeyValue,
};
use std::collections::HashMap;

fn make_request() {
    let tracer = global::tracer("service-a");
    let mut span = tracer.start("process_request");
    
    // Create baggage
    let mut baggage = Baggage::new();
    baggage.insert("user.id", "12345");
    baggage.insert("request.source", "mobile-app");
    
    // Attach to context
    let cx = Context::current()
        .with_span(span)
        .with_baggage(baggage);
    
    // Inject into HTTP headers
    let mut headers = HashMap::new();
    global::get_text_map_propagator(|propagator| {
        propagator.inject_context(&cx, &mut headers);
    });
    
    // Send request with headers
    send_http_request(&headers);
}
```

### Service B (downstream)

```rust theme={null}
use opentelemetry::{
    baggage::BaggageExt,
    global,
    trace::{Tracer, TraceContextExt},
    KeyValue,
};
use std::collections::HashMap;

fn handle_request(headers: HashMap<String, String>) {
    // Extract context from headers
    let parent_cx = global::get_text_map_propagator(|propagator| {
        propagator.extract(&headers)
    });
    
    // Read baggage
    let baggage = parent_cx.baggage();
    
    let tracer = global::tracer("service-b");
    let mut span = tracer
        .span_builder("handle_request")
        .start_with_context(&tracer, &parent_cx);
    
    // Add baggage values as span attributes
    if let Some(user_id) = baggage.get("user.id") {
        span.set_attribute(KeyValue::new("user.id", user_id.to_string()));
    }
    
    if let Some(source) = baggage.get("request.source") {
        span.set_attribute(KeyValue::new("request.source", source.to_string()));
    }
    
    // Process request...
    span.end();
}
```

## Common use cases

### 1. User identification

```rust theme={null}
let mut baggage = Baggage::new();
baggage.insert("user.id", "12345");
baggage.insert("user.email", "user@example.com");
baggage.insert("user.role", "admin");
```

### 2. Request tracking

```rust theme={null}
let mut baggage = Baggage::new();
baggage.insert("request.id", generate_request_id());
baggage.insert("correlation.id", correlation_id);
```

### 3. Feature flags

```rust theme={null}
let mut baggage = Baggage::new();
baggage.insert("feature.new_ui", "enabled");
baggage.insert("experiment.variant", "b");
```

### 4. Multi-tenancy

```rust theme={null}
let mut baggage = Baggage::new();
baggage.insert("tenant.id", "tenant-123");
baggage.insert("tenant.tier", "enterprise");
```

## Iterating over baggage

```rust theme={null}
use opentelemetry::baggage::Baggage;

let mut baggage = Baggage::new();
baggage.insert("key1", "value1");
baggage.insert("key2", "value2");

// Iterate over entries
for (key, (value, metadata)) in baggage.iter() {
    println!("{}: {} (metadata: {:?})", key, value, metadata);
}
```

## Adding baggage to telemetry

### Add to spans

```rust theme={null}
use opentelemetry::{baggage::BaggageExt, trace::TraceContextExt, Context, KeyValue};

let cx = Context::current();
let baggage = cx.baggage();
let span = cx.span();

// Add all baggage as span attributes
for (key, (value, _)) in baggage.iter() {
    span.set_attribute(KeyValue::new(key.to_string(), value.to_string()));
}
```

### Add to metrics

```rust theme={null}
use opentelemetry::{baggage::BaggageExt, Context, KeyValue};

let cx = Context::current();
let baggage = cx.baggage();

let mut attributes = vec![];
if let Some(tenant) = baggage.get("tenant.id") {
    attributes.push(KeyValue::new("tenant.id", tenant.to_string()));
}

counter.add(&cx, 1, &attributes);
```

## Best practices

<Tip>
  **Keep baggage small** - Baggage is sent with every request. Keep the size minimal to avoid network overhead.
</Tip>

<Warning>
  **No sensitive data** - Baggage propagates across all services and may be logged. Never put passwords, tokens, or PII in baggage.
</Warning>

<Note>
  **Explicit attachment** - Remember that baggage values don't automatically appear in telemetry. You must explicitly read and attach them.
</Note>

<Info>
  **Validation** - Baggage keys must follow RFC2616 token format. Invalid keys are rejected.
</Info>

## Baggage vs span attributes

| Feature              | Baggage                 | Span Attributes    |
| -------------------- | ----------------------- | ------------------ |
| Propagation          | Across services         | Within span only   |
| Visibility           | All downstream services | Current span       |
| Size limits          | 64 entries, 8KB total   | No hard limit      |
| Automatic attachment | No                      | Yes (to span)      |
| Use case             | Cross-cutting concerns  | Span-specific data |

## Related

<CardGroup cols={2}>
  <Card title="Propagators" icon="arrows-rotate" href="/advanced/propagators">
    Configure context propagation
  </Card>

  <Card title="Context propagation" icon="share-nodes" href="/concepts/context-propagation">
    Learn about context flow
  </Card>
</CardGroup>
