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

# Multi-Environment Config

> Manage staging and production DevHelm configurations with environment-specific overrides

By the end of this guide, you'll have separate monitoring configurations for staging and production, with shared base definitions and environment-specific overrides.

<Accordion title="Prerequisites">
  * DevHelm CLI installed
  * A `devhelm.yml` file — see [Monitoring as Code tutorial](/guides/monitoring-as-code)
  * Separate API tokens for each environment
</Accordion>

## Strategy: separate files

The simplest approach is one YAML file per environment:

```
repo/
├── devhelm.yml              # Production
├── devhelm.staging.yml      # Staging
└── .github/workflows/
    └── devhelm-deploy.yml
```

## Production config

```yaml theme={null}
version: "1"

tags:
  - name: production
    color: "#ef4444"

monitors:
  - name: API Health
    type: HTTP
    config:
      url: https://api.example.com/health
      method: GET
    frequencySeconds: 30
    regions:
      - us-east
      - eu-west
      - ap-south
    tags: [production]
    assertions:
      - config:
          type: status_code
          expected: "200"
          operator: equals
        severity: fail
      - config:
          type: response_time
          thresholdMs: 1000
        severity: fail

alertChannels:
  - name: Production Slack
    config:
      channelType: slack
      webhookUrl: ${SLACK_WEBHOOK_PRODUCTION}

  - name: PagerDuty On-Call
    config:
      channelType: pagerduty
      routingKey: ${PAGERDUTY_ROUTING_KEY}
```

## Staging config

Staging typically has longer intervals, fewer regions, and less aggressive alerting:

```yaml theme={null}
version: "1"

tags:
  - name: staging
    color: "#f59e0b"

monitors:
  - name: API Health (Staging)
    type: HTTP
    config:
      url: https://api.staging.example.com/health
      method: GET
    frequencySeconds: 300
    regions:
      - us-east
    tags: [staging]
    assertions:
      - config:
          type: status_code
          expected: "200"
          operator: equals
        severity: fail

alertChannels:
  - name: Staging Slack
    config:
      channelType: slack
      webhookUrl: ${SLACK_WEBHOOK_STAGING}
```

Key differences from production:

| Aspect                  | Production                   | Staging            |
| ----------------------- | ---------------------------- | ------------------ |
| Frequency               | 30s                          | 300s (5 min)       |
| Regions                 | 3                            | 1                  |
| Response time assertion | Yes (1000ms)                 | No                 |
| PagerDuty               | Yes                          | No                 |
| Alert channel           | Production Slack + PagerDuty | Staging Slack only |

## Deploy with environment-specific tokens

Each environment uses its own API token:

```yaml theme={null}
name: Deploy Monitoring
on:
  push:
    branches: [main]
    paths: ['devhelm.yml', 'devhelm.staging.yml']

jobs:
  deploy-staging:
    runs-on: ubuntu-latest
    environment: staging
    steps:
      - uses: actions/checkout@v4
      - uses: devhelmhq/setup-devhelm@v1
        with:
          api-token: ${{ secrets.DEVHELM_API_TOKEN_STAGING }}
      - run: devhelm validate devhelm.staging.yml
      - run: devhelm deploy -f devhelm.staging.yml --yes

  deploy-production:
    needs: deploy-staging
    runs-on: ubuntu-latest
    environment: production
    steps:
      - uses: actions/checkout@v4
      - uses: devhelmhq/setup-devhelm@v1
        with:
          api-token: ${{ secrets.DEVHELM_API_TOKEN }}
      - run: devhelm validate devhelm.yml
      - run: devhelm deploy -f devhelm.yml --yes
```

Staging deploys first. Production only deploys if staging succeeds.

## Secret management

Each environment needs its own secrets:

```bash theme={null}
# Production
devhelm secrets create --key SLACK_WEBHOOK_PRODUCTION --value https://hooks.slack.com/...
devhelm secrets create --key PAGERDUTY_ROUTING_KEY --value your-routing-key

# Staging (switch context or use a different token)
DEVHELM_API_TOKEN=$STAGING_TOKEN devhelm secrets create --key SLACK_WEBHOOK_STAGING --value https://hooks.slack.com/...
```

<Warning>
  Never share API tokens between environments. Use separate tokens so staging changes can't accidentally affect production.
</Warning>

## Next steps

<CardGroup cols={2}>
  <Card title="CI/CD pipeline" icon="rotate" href="/guides/ci-cd-pipeline">
    Full GitHub Actions deployment workflow.
  </Card>

  <Card title="Monitoring as Code tutorial" icon="file-code" href="/guides/monitoring-as-code">
    YAML format and deploy workflow.
  </Card>

  <Card title="Migrating from Dashboard" icon="right-from-bracket" href="/guides/migrating-from-dashboard">
    Move existing monitors to config files.
  </Card>
</CardGroup>
