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

# Multi-Instance Tracing

> Run multiple HoneyHiveTracer instances for multi-tenant apps, A/B tests, or per-agent routing so each instance exports to the right project and session.

## Overview

HoneyHive supports multiple tracer instances in a single application. Each instance maintains its own session context, configuration, and OTel `TracerProvider`. Instances do not share context.

Projects are selected by the API key. Use a separate project-scoped API key when a tracer should write to a different HoneyHive project. Use metadata or session enrichment when traces should stay in the same project.

```mermaid theme={null}
graph TB
    subgraph "Application"
        A[Request 1] --> B[Tracer 1]
        C[Request 2] --> D[Tracer 2]
        E[Request 3] --> F[Tracer 3]
    end
    
    subgraph "Isolated Sessions"
        B --> G["Session A (tenant: acme)"]
        D --> H["Session B (tenant: globex)"]
        F --> I["Session C (tenant: acme)"]
    end
    
    G --> J[HoneyHive API]
    H --> J
    I --> J
```

***

## Use Cases

### Environment-Based Tracing

Send each environment to the project scoped to its API key:

```python theme={null}
import os
from honeyhive import HoneyHiveTracer, trace

env = os.getenv("ENVIRONMENT", "development")
api_keys = {
    "development": os.environ["HH_API_KEY_DEVELOPMENT"],
    "staging": os.environ["HH_API_KEY_STAGING"],
    "production": os.environ["HH_API_KEY_PRODUCTION"],
}

tracer = HoneyHiveTracer.init(
    api_key=api_keys[env],
    source=env
)
```

### Multi-Tenant SaaS

Give each tenant its own tracer and session metadata. If tenants need project-level isolation, select a project-scoped API key for that tenant:

```python theme={null}
from honeyhive import HoneyHiveTracer
import os

TENANT_API_KEYS = {
    "acme": os.environ["HH_API_KEY_TENANT_ACME"],
    "globex": os.environ["HH_API_KEY_TENANT_GLOBEX"],
}

def handle_request(request):
    tracer = HoneyHiveTracer.init(
        api_key=TENANT_API_KEYS[request.tenant_slug],
        source="production"
    )

    tracer.enrich_session({
        "tenant_id": request.tenant_id,
        "plan": request.tenant_plan
    })

    return process_with_tracer(request, tracer)
```

### A/B Testing

Run different configurations side-by-side and compare them with session metadata:

```python theme={null}
from honeyhive import HoneyHiveTracer, trace
import os

def ab_test_handler(request):
    variant = get_ab_variant(request.user_id)

    tracer = HoneyHiveTracer.init(
        api_key=os.environ["HH_API_KEY"],
        source="production"
    )

    tracer.enrich_session({
        "variant": variant,
        "user_id": request.user_id
    })

    if variant == "A":
        return process_with_gpt4(request, tracer)
    else:
        return process_with_claude(request, tracer)
```

### Feature Isolation

Route different features to projects scoped by separate API keys:

```python theme={null}
from honeyhive import HoneyHiveTracer, trace
import os

customer_tracer = HoneyHiveTracer.init(
    api_key=os.environ["HH_API_KEY_CUSTOMER_EXPERIENCE"],
    source="production"
)

admin_tracer = HoneyHiveTracer.init(
    api_key=os.environ["HH_API_KEY_INTERNAL_TOOLS"],
    source="production"
)

@trace(tracer=customer_tracer)
def handle_customer_query(query: str) -> str:
    ...

@trace(tracer=admin_tracer)
def generate_internal_report(data: dict) -> str:
    ...
```

***

## Per-Request Initialization

For full isolation, initialize a tracer per request:

```python theme={null}
import os
from honeyhive import HoneyHiveTracer
from flask import Flask, request

app = Flask(__name__)

@app.route("/api/process", methods=["POST"])
def handle():
    tracer = HoneyHiveTracer.init(
        api_key=os.environ["HH_API_KEY"],
        source="api-server"
    )

    tracer.enrich_session({
        "endpoint": request.path,
        "method": request.method
    })

    result = process_request(request.json)
    tracer.force_flush()
    return result
```

***

## Thread Safety

HoneyHive uses Python's `contextvars` for thread safety. When using thread pools, propagate context explicitly:

```python theme={null}
from concurrent.futures import ThreadPoolExecutor
import contextvars

def process_in_threads(items, tracer):
    def process_item(item):
        return do_work(item)

    with ThreadPoolExecutor(max_workers=4) as executor:
        futures = [
            executor.submit(contextvars.copy_context().run, process_item, item)
            for item in items
        ]
        return [f.result() for f in futures]
```

<Warning>
  Copy the context for **each** `executor.submit()` call. Reusing a single context object across threads causes race conditions. See [Multi-Threading](/v2/tracing/multithreading) for details.
</Warning>

***

## Best Practices

* Keep tracer instances in a central registry - create once, reuse many times
* Use project-scoped API keys when a tracer should write to a different project
* Store API keys in environment variables or a secret manager, never hard-code them
* Use metadata to differentiate when possible, rather than creating additional tracers
* 2-5 tracers per application is typical and performant

***

## Performance

| Metric          | Impact                            |
| --------------- | --------------------------------- |
| Memory          | \~100KB per tracer instance       |
| Network         | Batched, async export per tracer  |
| Span Processing | Each tracer has its own processor |

***

## Related

<CardGroup cols={2}>
  <Card title="Production Deployment" icon="rocket" href="/v2/tutorials/production-deployment">
    Initialization patterns for production environments
  </Card>

  <Card title="Multi-Threaded Tracing" icon="gears" href="/v2/tracing/multithreading">
    Context propagation across threads
  </Card>
</CardGroup>
