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

# Environments

> Separate development, staging, and production traces with dedicated environment tracking

## How Environments Work

<Steps>
  <Step title="Set environment via environment variable or SDK">
    Configure the environment using the `ABV_TRACING_ENVIRONMENT` environment variable (recommended) or the `environment` parameter during client initialization. Common values: `production`, `staging`, `development`, `dev`.

    ```bash title=".env" theme={null}
    ABV_TRACING_ENVIRONMENT=production
    ```
  </Step>

  <Step title="All events tagged with environment">
    Once configured, every trace, observation (span/event/generation), score, and session automatically includes the environment attribute. This happens transparently without code changes.
  </Step>

  <Step title="Filter by environment in the ABV UI">
    Use the environment filter in the ABV dashboard navigation bar to switch between environments. The filter applies across all views, showing only events from the selected environment.
  </Step>

  <Step title="Analyze metrics by environment">
    Compare performance, costs, and error rates between environments. Identify staging vs production differences. Track environment-specific trends over time.
  </Step>

  <Step title="Reuse prompts and datasets across environments">
    Create prompts in staging, test them thoroughly, then use the same prompts in production. Share datasets between environments while keeping traces separate.
  </Step>
</Steps>

## Why Use Environments?

<AccordionGroup>
  <Accordion title="Separate Production from Development" icon="layer-group">
    **The Challenge:** Your team has 10 developers running code locally, 3 staging deployments for different features, and 1 production deployment. All traces flow into the same ABV project, creating chaos in your dashboard.

    **The Solution:** Set environment variables per deployment context.

    **Locally (.env.local):**

    ```bash theme={null}
    ABV_TRACING_ENVIRONMENT=dev
    ```

    **Staging (Kubernetes/Docker):**

    ```bash theme={null}
    ABV_TRACING_ENVIRONMENT=staging
    ```

    **Production (Kubernetes/Docker):**

    ```bash theme={null}
    ABV_TRACING_ENVIRONMENT=production
    ```

    **The Result:** Production dashboard shows only real user traffic. Developers can experiment freely in `dev` without polluting production data. Staging provides a clean pre-production testing ground.

    **Operational benefit:** On-call engineers filter to `production` and see only what matters. No false alarms from dev experiments or staging tests.
  </Accordion>

  <Accordion title="Staged Rollouts & Safe Testing" icon="stairs">
    **The Challenge:** You're deploying a new RAG implementation that changes how documents are chunked. It might improve accuracy or it might break everything. You need to validate before exposing to customers.

    **The Solution:** Deploy the change to staging first with environment separation.

    ```python theme={null}
    # This runs in staging with ABV_TRACING_ENVIRONMENT=staging
    @observe()
    def process_document_v2(doc):
        # New chunking logic
        chunks = new_chunking_strategy(doc)
        abv.update_current_trace(metadata={"chunking": "v2"})
        return chunks
    ```

    **The Result:**

    1. Deploy to staging, generate traces tagged `staging`
    2. Analyze staging performance, accuracy, cost
    3. Compare staging metrics to production baseline
    4. If good, deploy to production with confidence
    5. If issues found, fix in staging first

    **Best practice:** Keep staging as production-like as possible (same models, similar data volume) so staging results predict production behavior accurately.
  </Accordion>

  <Accordion title="Debugging with Full Context" icon="magnifying-glass-plus">
    **The Challenge:** Customer support forwards a bug report: "The LLM isn't working." You need to know: Is this production? Staging? Someone's local dev environment? Without context, you can't prioritize or debug effectively.

    **The Solution:** Every trace includes environment information, visible in the UI and queryable via API.

    **The Result:**

    * See `environment: production` → drop everything, production is down
    * See `environment: staging` → important but not urgent, investigate during business hours
    * See `environment: dev` → probably a developer debugging, low priority

    **Communication benefit:** When asking for help, developers can say "check trace XYZ in staging" and everyone knows exactly where to look. No ambiguity.
  </Accordion>

  <Accordion title="Cost Attribution by Environment" icon="dollar-sign">
    Filter cost dashboards by environment to identify spending on non-production workloads.

    **Example breakdown:**

    * Production: 70% (real customer value)
    * Staging: 25% (integration tests, load tests)
    * Dev: 5% (developer experiments)

    **Optimization**: Identify expensive staging tests using premium models and switch to cheaper alternatives for testing.
  </Accordion>

  <Accordion title="Compliance & Audit Trails" icon="clipboard-check">
    **The Challenge:** Your compliance team asks: "Can you prove that customer PII is only processed in production, never in development?" Without environment separation, this is nearly impossible to demonstrate.

    **The Solution:** Use environments to create clear separation boundaries.

    ```python theme={null}
    import os

    ENVIRONMENT = os.getenv("ABV_TRACING_ENVIRONMENT", "dev")

    @observe()
    def process_customer_data(customer_id, pii_data):
        if ENVIRONMENT != "production":
            raise ValueError("PII processing only allowed in production")

        # Process PII only in production environment
        # All traces tagged with environment=production
    ```

    **The Result:** Audit logs show PII traces exist only in `production` environment. Development and staging use synthetic data only. Clear compliance demonstration.

    **Bonus:** Combine with [RBAC](/developer/platform/administration/role-based-access-controls) to restrict who can view production traces containing sensitive data.
  </Accordion>

  <Accordion title="Shared Resources Across Environments" icon="share-nodes">
    **The Challenge:** You've crafted the perfect prompt in staging after days of iteration. Now you need to use the exact same prompt in production. Manually copying risks errors and version drift.

    **The Solution:** ABV prompts and datasets are shared across environments within a project. Create in staging, reference by name in production.

    **Staging (create prompt):**

    ```python theme={null}
    # Iterate and refine prompt in staging
    abv.create_prompt(
        name="customer-support-v2",
        template="You are a helpful customer support agent..."
    )
    ```

    **Production (use same prompt):**

    ```python theme={null}
    # Use the same prompt in production
    prompt = abv.get_prompt("customer-support-v2")
    response = llm.complete(prompt.render(context=user_query))
    ```

    **The Result:** Prompts tested in staging work identically in production. Version control ensures consistency. Test thoroughly before production rollout.
  </Accordion>
</AccordionGroup>

## Implementation Guide

<AccordionGroup>
  <Accordion title="Python SDK" icon="python">
    <Tabs>
      <Tab title="Environment Variable (Recommended)">
        The simplest and most common approach:

        **Create a `.env` file:**

        ```bash title=".env" theme={null}
        ABV_API_KEY=sk-abv-...
        ABV_HOST=https://app.abv.dev  # or https://eu.app.abv.dev for EU
        ABV_TRACING_ENVIRONMENT=production
        ```

        **Load and use in your code:**

        ```python theme={null}
        from abvdev import get_client, observe
        from dotenv import load_dotenv

        # Load environment variables from .env file
        load_dotenv()

        # Get client - automatically uses ABV_TRACING_ENVIRONMENT
        abv = get_client()

        # All traces now tagged with environment=production
        @observe()
        def process_data(data):
            # Your code here
            return result

        process_data({"query": "test"})
        ```

        **Why this approach:**

        * Environment variables are deployment-best-practice
        * No code changes needed between dev/staging/prod
        * Works with Docker, Kubernetes, serverless platforms
        * Prevents accidentally hardcoding wrong environment
      </Tab>

      <Tab title="Client Initialization Parameter">
        For cases where you need programmatic control:

        ```python theme={null}
        from abvdev import ABV
        import os

        # Determine environment from multiple sources
        environment = (
            os.getenv("DEPLOYMENT_ENV") or  # Check custom env var
            os.getenv("STAGE") or           # Check alternative var
            "development"                    # Fallback
        )

        abv = ABV(
            api_key="sk-abv-...",
            host="https://app.abv.dev",
            environment=environment
        )

        # All operations now tagged with computed environment
        with abv.start_as_current_span(name="my-operation") as span:
            # Your code here
            pass
        ```

        **When to use:** Dynamic environment detection, migration from legacy systems, multi-tenant applications with per-tenant environments.

        **Note:** If both `ABV_TRACING_ENVIRONMENT` and the `environment` parameter are set, the parameter takes precedence.
      </Tab>
    </Tabs>

    **Installation:**

    ```bash theme={null}
    pip install abvdev python-dotenv
    ```

    **Environment naming rules:**

    * Must match regex: `^(?!abv)[a-z0-9-_]+$`
    * Cannot start with "abv"
    * Only lowercase letters, numbers, hyphens, underscores
    * Maximum 40 characters
    * Examples: `production`, `staging`, `dev`, `local`, `qa-team-1`

    See [Python SDK docs](/developer/sdks/python/overview) for more details.
  </Accordion>

  <Accordion title="JavaScript/TypeScript SDK" icon="js">
    <Tabs>
      <Tab title="Environment Variable (Recommended)">
        **Create a `.env` file:**

        ```bash title=".env" theme={null}
        ABV_API_KEY=sk-abv-...
        ABV_BASE_URL=https://app.abv.dev  # or https://eu.app.abv.dev for EU
        ABV_TRACING_ENVIRONMENT=production
        ```

        **Create `instrumentation.ts`:**

        ```typescript title="instrumentation.ts" theme={null}
        import dotenv from "dotenv";
        dotenv.config();

        import { NodeSDK } from "@opentelemetry/sdk-node";
        import { ABVSpanProcessor } from "@abvdev/otel";

        const sdk = new NodeSDK({
          spanProcessors: [
            new ABVSpanProcessor({
              apiKey: process.env.ABV_API_KEY,
              baseUrl: process.env.ABV_BASE_URL,
              // Environment is automatically read from ABV_TRACING_ENVIRONMENT
              exportMode: "immediate",
              flushAt: 1,
              flushInterval: 1,
            })
          ],
        });

        sdk.start();
        ```

        **Import at the top of your application:**

        ```typescript title="index.ts" theme={null}
        import "./instrumentation";  // Must be first import

        import { startActiveObservation } from "@abvdev/tracing";

        async function main() {
          await startActiveObservation("my-operation", async (span) => {
            // All traces tagged with environment from ABV_TRACING_ENVIRONMENT
            span.update({ input: { query: "test" } });
          });
        }

        main();
        ```
      </Tab>

      <Tab title="Different Environments">
        **Development (.env.local):**

        ```bash title=".env.local" theme={null}
        ABV_TRACING_ENVIRONMENT=dev
        ```

        **Staging (docker-compose.yml):**

        ```yaml theme={null}
        services:
          app:
            environment:
              - ABV_TRACING_ENVIRONMENT=staging
        ```

        **Production (Kubernetes secret/configmap):**

        ```yaml theme={null}
        env:
          - name: ABV_TRACING_ENVIRONMENT
            value: "production"
        ```
      </Tab>
    </Tabs>

    **Installation:**

    ```bash theme={null}
    npm install @abvdev/tracing @abvdev/otel @opentelemetry/sdk-node dotenv
    ```

    See [JS/TS SDK docs](/developer/sdks/js-ts/overview) for complete reference.
  </Accordion>

  <Accordion title="OpenTelemetry" icon="infinity">
    When using OpenTelemetry directly, ABV recognizes these attributes for environment:

    * `abv.environment` (recommended)
    * `deployment.environment.name`
    * `deployment.environment`

    <Tabs>
      <Tab title="Resource Attributes (Global)">
        Set environment globally for all spans using resource attributes:

        ```python theme={null}
        import os
        from opentelemetry import trace
        from opentelemetry.sdk.trace import TracerProvider
        from opentelemetry.sdk.resources import Resource
        from abvdev import ABV

        # Set environment via resource attributes
        os.environ["OTEL_RESOURCE_ATTRIBUTES"] = "abv.environment=staging"

        # Initialize tracer provider
        resource = Resource.create({"abv.environment": "staging"})
        provider = TracerProvider(resource=resource)
        trace.set_tracer_provider(provider)

        # Initialize ABV
        abv = ABV(
            api_key="sk-abv-...",
            host="https://app.abv.dev"
        )

        # All spans automatically tagged with environment=staging
        tracer = trace.get_tracer(__name__)
        with tracer.start_as_current_span("my-operation") as span:
            # Your code here
            pass

        abv.flush()
        ```
      </Tab>

      <Tab title="Per-Span Attributes">
        Override environment for specific spans:

        ```python theme={null}
        from opentelemetry import trace
        from abvdev import ABV

        abv = ABV(
            api_key="sk-abv-...",
            host="https://app.abv.dev"
        )

        tracer = trace.get_tracer(__name__)

        # Regular production operation
        with tracer.start_as_current_span("production-op") as span:
            span.set_attribute("abv.environment", "production")
            # This span tagged environment=production

        # Testing operation, override to staging
        with tracer.start_as_current_span("test-op") as span:
            span.set_attribute("abv.environment", "staging")
            # This span tagged environment=staging

        abv.flush()
        ```

        **When to use:** Multi-tenant systems, gradual migrations, or advanced scenarios requiring different environments within the same process.
      </Tab>

      <Tab title="Alternative Attributes">
        ABV also recognizes standard OpenTelemetry environment attributes:

        ```python theme={null}
        # Using deployment.environment.name (OTel convention)
        span.set_attribute("deployment.environment.name", "production")

        # Using deployment.environment (shorter form)
        span.set_attribute("deployment.environment", "production")

        # All three are equivalent in ABV
        ```
      </Tab>
    </Tabs>

    See [OpenTelemetry Integration](/developer/sdks/python/opentelemetry) for more details.
  </Accordion>
</AccordionGroup>

## Filtering & Analysis

### UI Filtering

In the ABV dashboard, use the environment filter in the navigation bar to switch between environments. The filter applies across:

* Traces list
* Sessions view
* Scores and evaluations
* Custom dashboards
* Analytics and metrics

### API Filtering

Filter by environment when querying the ABV API:

```bash theme={null}
curl https://app.abv.dev/api/v1/traces?environment=production \
  -H "Authorization: Bearer sk-abv-..."
```

See [API Reference](/developer/platform/api-data-platform/public-api) for complete filtering options.

## Best Practices

<Tip>
  **Use environment variables for configuration.** Set `ABV_TRACING_ENVIRONMENT` via environment variables rather than hardcoding in your application. This prevents accidentally deploying wrong environment settings and follows 12-factor app principles.
</Tip>

<Tip>
  **Establish naming conventions early.** Decide on environment names (`production` vs `prod`, `development` vs `dev`) and document them for your team. Consistency prevents filtering confusion.
</Tip>

<Warning>
  **Don't use environments for multi-tenancy.** Environments are for deployment contexts (dev/staging/prod), not for separating customer data. Use [metadata](/developer/basic-features/metadata) or separate ABV projects for multi-tenant isolation.
</Warning>

<Tip>
  **Keep staging production-like.** Configure staging with the same models, similar data volumes, and realistic workloads. The more staging resembles production, the more valuable its testing becomes.
</Tip>

<Info>
  **Default environment:** If no environment is specified, ABV uses `default` as the environment name. Explicitly set environments even in development to avoid mixing `default` data from different contexts.
</Info>

## Environments vs Tags vs Metadata

Choosing the right feature:

| Feature                                            | Best For                                      | Example Use Cases                               |
| -------------------------------------------------- | --------------------------------------------- | ----------------------------------------------- |
| **Environments**                                   | Deployment contexts with formal separation    | `production`, `staging`, `development`          |
| **[Tags](/developer/basic-features/tags)**         | Simple categorization, experiments, filtering | `rag`, `beta`, `few-shot`, `v2.1.0`             |
| **[Metadata](/developer/basic-features/metadata)** | Structured data, detailed attributes          | `{"tenant_id": "acme", "user_tier": "premium"}` |

**When to use together:**

* Set environment to `production` AND use tags like `beta` for gradual feature rollouts
* Set environment to `staging` AND use metadata for detailed test scenario tracking
* All traces should have an environment, most will have metadata, many will have tags

## Related Features

<CardGroup cols={2}>
  <Card title="Tags" icon="tags" href="/developer/basic-features/tags">
    Add simple string labels for flexible categorization and filtering
  </Card>

  <Card title="Metadata" icon="database" href="/developer/basic-features/metadata">
    Attach structured key-value data for detailed analytics and querying
  </Card>

  <Card title="Role-Based Access Control" icon="user-shield" href="/developer/platform/administration/role-based-access-controls">
    Control who can view and modify production data with granular permissions
  </Card>

  <Card title="Data Retention" icon="clock" href="/developer/platform/administration/data-retention">
    Configure different retention policies for production vs staging data
  </Card>
</CardGroup>
