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

# Monitor multiple environments

> Choose how to test and continuously monitor development, staging, and production environments with Checkly.

Checkly does not create a separate Environment resource. Instead, you combine CLI projects, environment variables, and your CI/CD pipeline to target each application environment.

Use a separate Checkly CLI project for every long-lived environment that you want to monitor continuously. Use `checkly test` without deploying a project when you only need to validate an ephemeral environment, such as a pull request preview.

## Choose an approach

| What you want to do | Recommended approach |
| - | - |
| Test an ephemeral preview deployment | Run `checkly test` with temporary environment variables. Do not deploy it as a scheduled monitor. |
| Continuously monitor the same checks in development, staging, and production | Deploy the same check code as a separate CLI project for each environment. Give every project a unique, stable `logicalId`. |
| Continuously monitor different checks in each environment | Use a separate project for each environment and select shared and environment-specific check files in the project configuration. |

> [!NOTE]
>
> A Checkly CLI project is a deployment boundary, not the same thing as a Git branch or application environment. Your pipeline decides which branch deploys which project.

## Test an ephemeral environment

Pass runtime values to `checkly test` with `--env` (`-e`) or `--env-file`. The values apply only to that test session and do not update your scheduled monitors.

```bash Terminal theme={null}
npx checkly test \
  --env ENVIRONMENT_URL="https://preview-123.example.com" \
  --env API_TOKEN="$PREVIEW_API_TOKEN"
```

This approach works well for pull request previews and other short-lived deployments. See [CI/CD](https://www.checklyhq.com/docs/integrations/ci-cd/overview.md) for the recommended test-before-deploy workflow.

## Continuously monitor multiple environments

The following example deploys one shared API check to development, staging, and production. Each deployment has:

* A unique project identity and separate deployment history
* The same project-scoped check and group logical IDs
* Its own URL and secret API token
* Its own schedule, locations, and tags

> **Prerequisites**
>
> * A Checkly account and a Checkly CLI project
> * `CHECKLY_API_KEY` and `CHECKLY_ACCOUNT_ID` configured in your CI provider
> * A persistent deployment URL and credentials for each environment
> * A CI branch or deployment event that identifies the target environment

**1. Define a stable project identity for each environment**

Read the target environment from your CI pipeline and map it to a unique project `logicalId`.

```typescript checkly.config.ts theme={null}
import { defineConfig, type Region } from "checkly"
import { Frequency } from "checkly/constructs"

type Environment = "development" | "staging" | "production"

const environments: Record<Environment, {
  projectName: string
  logicalId: string
  frequency: Frequency
  locations: (keyof Region)[]
}> = {
  development: {
    projectName: "My app - Development",
    logicalId: "my-app-development",
    frequency: Frequency.EVERY_30M,
    locations: ["us-east-1"],
  },
  staging: {
    projectName: "My app - Staging",
    logicalId: "my-app-staging",
    frequency: Frequency.EVERY_10M,
    locations: ["us-east-1"],
  },
  production: {
    projectName: "My app - Production",
    logicalId: "my-app-production",
    frequency: Frequency.EVERY_5M,
    locations: ["us-east-1", "eu-west-1"],
  },
}

const environment = process.env.CHECKLY_ENVIRONMENT as Environment | undefined

if (!environment || !environments[environment]) {
  throw new Error(
    "Set CHECKLY_ENVIRONMENT to development, staging, or production"
  )
}

const target = environments[environment]

export default defineConfig({
  projectName: target.projectName,
  logicalId: target.logicalId,
  checks: {
    activated: true,
    checkMatch: "**/__checks__/**/*.check.ts",
    frequency: target.frequency,
    locations: target.locations,
    tags: [environment],
  },
})
```

Keep each project `logicalId` stable. Changing it creates a different project instead of updating the existing environment's monitors.

**2. Store environment-specific runtime values with the checks**

Define values on a check or group when scheduled runs need them. In this example, the CLI reads the values from CI while deploying and stores them on the environment's check group.

```typescript __checks__/api.check.ts theme={null}
import {
  ApiCheck,
  AssertionBuilder,
  CheckGroupV2,
} from "checkly/constructs"

const environment = process.env.CHECKLY_ENVIRONMENT
const environmentUrl = process.env.ENVIRONMENT_URL
const apiToken = process.env.API_TOKEN

if (!environment || !environmentUrl || !apiToken) {
  throw new Error(
    "Set CHECKLY_ENVIRONMENT, ENVIRONMENT_URL, and API_TOKEN"
  )
}

const environmentGroup = new CheckGroupV2("application", {
  name: `My app - ${environment}`,
  tags: [environment],
  environmentVariables: [
    { key: "ENVIRONMENT_URL", value: environmentUrl },
    { key: "API_TOKEN", value: apiToken, secret: true },
  ],
})

new ApiCheck("api-health", {
  name: `API health - ${environment}`,
  group: environmentGroup,
  request: {
    method: "GET",
    url: "{{{ENVIRONMENT_URL}}}/health",
    headers: [
      { key: "Authorization", value: "Bearer {{{API_TOKEN}}}" },
    ],
    assertions: [AssertionBuilder.statusCode().equals(200)],
  },
})
```

The `application` and `api-health` logical IDs can stay the same because resource logical IDs are scoped to their CLI project. Setting `secret: true` prevents Checkly from exposing the token after it is saved.

**3. Deploy the project that matches the application environment**

Map each persistent application environment to one Checkly project in your pipeline. Run the matching command after that environment's application deployment succeeds.

| Application branch | `CHECKLY_ENVIRONMENT` | Checkly project `logicalId` |
| - | - | - |
| `develop` | `development` | `my-app-development` |
| `staging` | `staging` | `my-app-staging` |
| `main` | `production` | `my-app-production` |

For example, the staging deployment job would run:

```bash Terminal theme={null}
CHECKLY_ENVIRONMENT=staging \
ENVIRONMENT_URL="https://staging-api.example.com" \
API_TOKEN="$STAGING_API_TOKEN" \
npx checkly deploy
```

The production job uses the same source files but supplies production values:

```bash Terminal theme={null}
CHECKLY_ENVIRONMENT=production \
ENVIRONMENT_URL="https://api.example.com" \
API_TOKEN="$PRODUCTION_API_TOKEN" \
npx checkly deploy
```

Review the deployment changes before confirming them. After you have verified the mapping, a non-interactive CI job can use `--force` to skip the confirmation prompt.

> [!WARNING]
>
> A deploy reconciles only the project selected by its `logicalId`, but resources removed from that project are deleted by default. Run [`checkly deploy --preview`](https://www.checklyhq.com/docs/cli/checkly-deploy#command-options) when changing branch mappings or environment-specific check selection.

## Run different checks in each environment

When an environment needs additional or different checks, keep shared checks in one directory and select the environment-specific directory from your configuration:

```typescript checkly.config.ts theme={null}
const sharedChecks = "**/__checks__/shared/**/*.check.ts"
const environmentChecks = `**/__checks__/${environment}/**/*.check.ts`

export default defineConfig({
  projectName: target.projectName,
  logicalId: target.logicalId,
  checks: {
    checkMatch: [sharedChecks, environmentChecks],
    frequency: target.frequency,
    locations: target.locations,
    tags: [environment],
  },
})
```

For example, `__checks__/shared/` can contain health and login checks, while `__checks__/production/` contains production-only purchase checks. Each environment remains authoritative for its own deployed project.

## Understand environment variable behavior

| Variable source | Available when | Persists for scheduled monitoring |
| - | - | - |
| Shell or CI environment | The CLI parses your config and constructs | Only when the value is written into a deployed construct, such as a group environment variable |
| `checkly test --env` or `--env-file` | That test session runs in Checkly | No |
| Check- or group-level variable | A deployed check runs | Yes, for that check or group |
| Global variable | Any check in the account runs | Yes, account-wide |

Prefer check- or group-level variables when the same key needs a different value in each environment. A global `ENVIRONMENT_URL`, for example, can hold only one account-wide value and is therefore not a good fit for separate development, staging, and production targets.

Use [secrets](https://www.checklyhq.com/docs/platform/secrets.md) for credentials, tokens, and other sensitive values. For more detail about build-time and runtime values, see [CLI environment variables](https://www.checklyhq.com/docs/cli/environment-variables.md) and [environment variables and secrets](https://www.checklyhq.com/docs/platform/variables.md).

## Playwright Check Suites

For Playwright Check Suites, keep URLs and credentials in runtime environment variables and read them from `process.env` in your Playwright configuration or fixtures. The project-per-environment model remains the same.

See [Turn your Playwright tests into monitors](https://www.checklyhq.com/docs/guides/playwright-testing-to-monitoring.md#step-1-pick-the-tests-that-become-monitors) for switching `baseURL` between local and Checkly runs, and the [built-in environment variables](https://www.checklyhq.com/docs/detect/synthetic-monitoring/playwright-checks/environment-variables.md) for finer control.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.