How to Configure Cypress for Different Environments: A Complete Guide to Multi-Env Testing

Cypress supports environment-specific testing through a combination of cypress.config.{js|ts} files with named configurations blocks, CLI flags, CYPRESS_-prefixed environment variables, and optional cypress.env.json files.

Cypress provides a flexible configuration system that lets you tailor test runs for development, staging, production, or any custom environment without maintaining separate config files. By leveraging the defineConfig helper and the configurations key, you can maintain a single source-controlled cypress.config.js or cypress.config.ts while targeting multiple deployment targets.

Using Named Configurations for Multiple Environments

The most robust way to configure Cypress for different environments is to define named configuration blocks inside your main config file. When you export your configuration using defineConfig, you can include a top-level configurations object containing environment-specific overrides.

In system-tests/projects/config-with-ts/cypress.config.ts, the test suite demonstrates how to structure a TypeScript config file that supports multiple environments:

// cypress.config.ts
import { defineConfig } from 'cypress'

export default defineConfig({
  // Global defaults applied to all environments
  pageLoadTimeout: 60000,
  screenshotsFolder: 'cypress/screenshots',
  video: true,

  // Per-environment overrides
  configurations: {
    dev: {
      baseUrl: 'http://localhost:3000',
      env: {
        API_URL: 'http://localhost:4000/api',
      },
    },
    staging: {
      baseUrl: 'https://staging.example.com',
      env: {
        API_URL: 'https://staging.api.example.com',
      },
    },
    prod: {
      baseUrl: 'https://app.example.com',
      env: {
        API_URL: 'https://api.example.com',
      },
    },
  },

  e2e: {
    setupNodeEvents(on, config) {
      // Environment-specific Node event handlers
      return config
    },
  },
})

When you select a configuration, Cypress merges the chosen block into the base config, layer by layer. This pattern keeps all environment definitions in one place while avoiding duplication of shared settings like timeouts or folder paths.

Switching Environments via CLI and Environment Variables

Cypress offers two primary mechanisms for selecting which named configuration to use at runtime: CLI flags and environment variables.

CLI flag method (ideal for local testing):

cypress run --config-file cypress.config.ts --config configurations=staging

Environment variable method (preferred for CI/CD pipelines):

CYPRESS_configurations=prod cypress run

Any configuration key can be overridden via the CYPRESS_ prefix. For example, CYPRESS_baseUrl=https://staging.example.com temporarily replaces the baseUrl defined in your config file. According to the application lifecycle documentation in guides/app-lifecycle.md, these environment variables are processed before the config file is evaluated, ensuring they take precedence over file-based settings.

You can also pass arbitrary config values directly:

cypress run --config baseUrl=https://staging.example.com,viewportWidth=1280

Managing Environment Variables and Secrets

For values that change per environment but should not be hardcoded—such as API tokens or feature flags—Cypress supports a cypress.env.json file placed in your project root. This JSON file loads before the config file evaluation, making its keys available during configuration setup.

// cypress.env.json
{
  "API_TOKEN": "abc123",
  "FEATURE_X_ENABLED": true
}

As implemented in the Cypress monorepo, the legacy Cypress.env() API is being phased out in favor of the newer Cypress.expose() API. To enforce this migration, set allowCypressEnv: false in your config:

export default defineConfig({
  allowCypressEnv: false,
  expose: {
    API_ENDPOINT: 'https://api.example.com',
    FEATURE_FLAG: true,
  },
})

The expose object makes these values available to your tests while keeping them out of the browser's global scope until explicitly requested. This approach is documented in cli/CHANGELOG.md as the forward-compatible strategy for environment variable management.

Separating E2E and Component Testing Configurations

Modern Cypress setups often run both end-to-end (E2E) and component tests against different targets. The same cypress.config file can contain separate e2e and component blocks, each with distinct baseUrl values and support files.

export default defineConfig({
  configurations: {
    dev: {
      baseUrl: 'http://localhost:3000',
    },
  },
  
  e2e: {
    baseUrl: 'https://staging.example.com', // Falls back to this if no config selected
    supportFile: 'cypress/support/e2e.ts',
  },
  
  component: {
    devServer: {
      framework: 'react',
      bundler: 'vite',
    },
    supportFile: 'cypress/support/component.ts',
  },
})

This structure allows component tests to run against a local Vite or Webpack dev server while E2E tests hit a fully deployed staging environment, all controlled from the same configuration source.

Configuration Schema and Validation

The canonical configuration schema is defined in packages/config/README.md, which documents validation logic used across the Cypress monorepo. All supported configuration options—including baseUrl, env, allowCypressEnv, and configurations—are typed in cli/types/cypress.d.ts.

When troubleshooting configuration issues, reference these source files to verify:

  • Valid keys within defineConfig
  • Type requirements for the configurations object
  • Merge behavior when combining CLI overrides with file-based settings

Summary

  • Named configurations: Use the configurations key inside defineConfig to create per-environment blocks for dev, staging, and production.
  • Runtime selection: Switch environments using --config configurations=name CLI flags or CYPRESS_configurations=name environment variables.
  • Variable management: Store sensitive values in cypress.env.json or use the expose config key with allowCypressEnv: false for modern variable handling.
  • Test type separation: Define separate blocks for e2e and component testing within the same file to target different servers.
  • Source references: Configuration behavior is implemented in system-tests/projects/config-with-ts/cypress.config.ts and documented in packages/config/README.md.

Frequently Asked Questions

How do I run Cypress against different URLs without changing the config file?

Use the CYPRESS_baseUrl environment variable or the --config baseUrl=<url> CLI flag. These overrides take precedence over values in cypress.config.{js|ts}, allowing you to target staging or production servers from the same configuration.

Can I disable the old Cypress.env() API?

Yes. Set allowCypressEnv: false in your defineConfig export. This forces your team to use the expose configuration object instead, which provides better type safety and is the recommended path forward according to the Cypress CLI changelog.

What is the difference between cypress.env.json and the configurations key?

cypress.env.json loads environment variables before config evaluation and is ideal for secrets or local overrides. The configurations key lives inside your main config file and defines complete environment profiles (including baseUrl, timeouts, and nested env objects) that you select via CLI flags.

How do I configure different settings for component tests versus E2E tests?

Define separate e2e and component blocks in your cypress.config file. Each block can specify its own baseUrl, supportFile, and setupNodeEvents function, allowing component tests to target a dev server while E2E tests hit a deployed application.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →