Resource library

QA How-To

Cypress parallelization: Examples

Copy practical Cypress parallelization examples for Cloud, GitHub Actions, GitLab CI, cross-browser groups, manual sharding, data isolation, and reports.

24 min read | 2,579 words

TL;DR

The standard Cypress parallelization example creates several CI workers that run `cypress run --record --parallel` with the same build ID and group. Use a matrix for worker count, keep spec discovery identical, and isolate all mutable data and artifacts.

Key Takeaways

  • Use one identical recorded command on every worker in a Cypress Cloud parallel group.
  • Build IDs identify a workflow attempt, while group names identify a test family inside that run.
  • GitHub matrix jobs and GitLab parallel jobs can both act as independent Cloud workers.
  • Cross-browser and component runs need distinct groups even when they share one recorded build.
  • Manual shards must print assignments, handle zero-spec partitions, and preserve unique artifact paths.
  • Provide every worker an explicit namespace for users, tenants, records, files, and reporter output.

A Cypress parallelization example needs more than --parallel. It must show how several CI workers join one run, how the shared build ID is formed, how the application starts on every worker, where secrets live, and how data plus artifacts remain isolated.

This cookbook provides complete patterns for Cypress Cloud, GitHub Actions, GitLab CI, cross-browser groups, component tests, and Cloud-free sharding. Replace project scripts, ports, and test-data endpoints with your repository's actual contract, but preserve the orchestration rules described with each example.

TL;DR

npx cypress run \\
  --record \\
  --parallel \\
  --group chrome-e2e \\
  --browser chrome \\
  --ci-build-id \"$RUN_ID-$RUN_ATTEMPT\"

Run that exact command on every worker in the chrome-e2e group. Set CYPRESS_RECORD_KEY through protected CI secrets and keep projectId in cypress.config.ts.

Example Distribution Required shared value Unique per worker
GitHub plus Cypress Cloud Dynamic spec assignment Build ID and group Matrix worker number
GitLab plus Cypress Cloud Dynamic spec assignment Pipeline-based build ID and group CI_NODE_INDEX
Cross-browser Cloud run Dynamic within each browser group Build ID Group name per browser
Static GitHub shard Fixed paths Source revision Shard and spec list
Node-computed shard Deterministic modulo partition Shard total Shard index and report file

1. Minimal Cypress Parallelization Example

First prove recording on one worker, then start the same parallel command on two or more workers. The Cypress config contains the public Cloud project identifier.

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

export default defineConfig({
  projectId: 'abc123',
  video: true,
  e2e: {
    baseUrl: 'http://127.0.0.1:4173',
    specPattern: 'cypress/e2e/**/*.cy.{js,jsx,ts,tsx}',
  },
})

Each worker receives the secret record key in the standard environment variable and runs:

export CYPRESS_RECORD_KEY="value-from-ci-secret-store"

npx cypress run \\
  --record \\
  --parallel \\
  --group chrome-e2e \\
  --browser chrome \\
  --ci-build-id "$CI_BUILD_ID"

Do not copy the export with a real value into a repository. In CI, map the secret directly into the step environment. Many supported CI providers expose an identifier Cypress recognizes automatically, so the explicit --ci-build-id is optional when detection is correct.

All workers in this group must discover the same specs. They do not need different --spec arguments, and adding them would defeat Cloud's common queue. Cloud assigns one whole spec at a time. When a worker finishes, it asks for another until no work remains.

If only one job runs the command, the run records and accepts the parallel option but has no second machine with which to share specs. Worker provisioning belongs to the CI configuration.

2. GitHub Actions with Four Cloud Workers

This example uses a matrix to produce four jobs. Each job checks out the same revision, installs from the lockfile, builds the Vite-style application, starts its own preview server, and joins one Cloud group.

name: E2E parallel

on:
  pull_request:
  workflow_dispatch:

jobs:
  cypress:
    runs-on: ubuntu-latest
    timeout-minutes: 30
    strategy:
      fail-fast: false
      matrix:
        worker: [1, 2, 3, 4]

    env:
      CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}
      CYPRESS_BUILD_ID: ${{ github.run_id }}-${{ github.run_attempt }}
      CYPRESS_WORKER_ID: ${{ matrix.worker }}

    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-node@v4
        with:
          node-version: 22
          cache: npm

      - run: npm ci
      - run: npm run build

      - name: Start preview server
        run: npm run preview -- --host 127.0.0.1 --port 4173 &

      - name: Wait for preview server
        shell: bash
        run: |
          for attempt in {1..60}; do
            if curl --fail --silent http://127.0.0.1:4173 >/dev/null; then
              exit 0
            fi
            sleep 1
          done
          echo "Application did not become ready"
          exit 1

      - name: Run Cypress
        run: |
          npx cypress run \
            --record \
            --parallel \
            --group chrome-e2e \
            --browser chrome \
            --ci-build-id "$CYPRESS_BUILD_ID"

      - name: Upload local artifacts
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: cypress-${{ matrix.worker }}
          path: |
            cypress/screenshots
            cypress/videos
          if-no-files-found: ignore

${{ github.run_id }} remains common to the workflow, and ${{ github.run_attempt }} distinguishes a rerun. ${{ matrix.worker }} must not be part of the Cypress build ID because that would create four separate recorded runs. It is useful for test-data ownership and artifact names.

fail-fast: false is a matrix policy that keeps sibling jobs from being canceled automatically by GitHub. Cypress Cloud auto-cancellation, if enabled, is a separate project decision.

3. GitLab CI with Native Parallel Jobs

GitLab's parallel keyword creates identical job instances. CI_NODE_INDEX distinguishes a worker, while CI_NODE_TOTAL provides the count. All instances use the same pipeline-based Cypress build ID.

stages:
  - test

cypress-e2e:
  stage: test
  image: cypress/browsers:24.14.1
  parallel: 4
  variables:
    CYPRESS_BUILD_ID: "$CI_PIPELINE_ID-$CI_PIPELINE_IID"
    CYPRESS_WORKER_ID: "$CI_NODE_INDEX"
  before_script:
    - npm ci
    - npm run build
    - npm run preview -- --host 0.0.0.0 --port 4173 &
    - |
      for attempt in $(seq 1 60); do
        curl --fail --silent http://127.0.0.1:4173 >/dev/null && break
        test "$attempt" -eq 60 && exit 1
        sleep 1
      done
  script:
    - >
      npx cypress run
      --record
      --parallel
      --group chrome-e2e
      --browser chrome
      --ci-build-id "$CYPRESS_BUILD_ID"
  artifacts:
    when: always
    name: "cypress-$CI_NODE_INDEX"
    paths:
      - cypress/screenshots/
      - cypress/videos/

Pin the Cypress browsers image supported by your repository and update it through normal dependency maintenance. The short tag above resolves to a published multi-browser image, but pin the full immutable tag or digest when reproducibility matters. A project that installs system Chrome another way can use its standard Node image.

Store CYPRESS_RECORD_KEY as a masked, protected GitLab CI variable. Do not declare the secret value in the YAML. GitLab is one of the providers Cypress can identify from CI variables, so an explicit build ID may be unnecessary. Keeping it visible in this example demonstrates the requirement and distinguishes manual pipeline reruns according to the chosen ID.

4. Cross-Browser Parallel Groups

Chrome and Firefox runs should use distinct group names because they are separate execution families. They can share one recorded build ID so Cypress Cloud presents them under one run.

strategy:
  fail-fast: false
  matrix:
    include:
      - browser: chrome
        group: chrome-e2e
        worker: 1
      - browser: chrome
        group: chrome-e2e
        worker: 2
      - browser: firefox
        group: firefox-e2e
        worker: 1
      - browser: firefox
        group: firefox-e2e
        worker: 2

steps:
  - uses: actions/checkout@v4
  - uses: actions/setup-node@v4
    with:
      node-version: 22
      cache: npm
  - run: npm ci
  - name: Run browser group
    env:
      CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}
    run: |
      npx cypress run \
        --record \
        --parallel \
        --browser "${{ matrix.browser }}" \
        --group "${{ matrix.group }}" \
        --ci-build-id "${{ github.run_id }}-${{ github.run_attempt }}"

This snippet omits application startup only to focus on grouping. Add the same build and readiness steps shown in the full GitHub example.

Workers within chrome-e2e share that group's Chrome spec queue. Firefox workers share a separate Firefox queue. Reusing one group name for incompatible browsers causes an inconsistent recorded group. The worker number can repeat across groups because it is only a local namespace input.

Cross-browser coverage increases service load and test result volume. A common strategy runs a primary browser on pull requests and broader groups nightly or before release. Choose based on supported user risk, not on the availability of matrix syntax.

5. End-to-End and Component Test Groups

Component and end-to-end tests use different Cypress testing types and often different setup, so record them as distinct groups. Both groups can run concurrently under one build ID.

strategy:
  fail-fast: false
  matrix:
    include:
      - type: e2e
        group: chrome-e2e
        command: "npx cypress run --e2e"
      - type: component
        group: chrome-component
        command: "npx cypress run --component"

steps:
  - uses: actions/checkout@v4
  - uses: actions/setup-node@v4
    with:
      node-version: 22
      cache: npm
  - run: npm ci
  - name: Run recorded test type
    env:
      CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}
      CI_BUILD_ID: ${{ github.run_id }}-${{ github.run_attempt }}
    run: |
      ${{ matrix.command }} \
        --record \
        --group "${{ matrix.group }}" \
        --ci-build-id "$CI_BUILD_ID"

The example has one worker per group, so it records concurrently but does not use --parallel. To parallelize either group, add multiple identical matrix rows for that group and add --parallel to its command. Grouping and parallelization are independent features of recorded runs.

Component jobs usually do not need a separately started application server because the Cypress dev server mounts components through the configured framework adapter. End-to-end jobs still need the application. Separate jobs let each type use appropriate caches, dependencies, browsers, and timeouts.

6. Monorepo Projects Under One Workflow

In a monorepo, each Cypress project may have its own Cloud projectId. A recorded run belongs to one Cloud project, so do not assume one build ID merges unrelated project IDs into one dashboard run. Use a group per application within its own project invocation and keep working directories explicit.

strategy:
  fail-fast: false
  matrix:
    include:
      - app: admin
        project: apps/admin
        group: admin-chrome
      - app: storefront
        project: apps/storefront
        group: storefront-chrome

steps:
  - uses: actions/checkout@v4
  - uses: actions/setup-node@v4
    with:
      node-version: 22
      cache: npm
  - run: npm ci
  - name: Run app tests
    env:
      CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}
    run: |
      npx cypress run \
        --project "${{ matrix.project }}" \
        --record \
        --group "${{ matrix.group }}"

This is a grouping example, not a parallel group, because each app appears once. Add duplicate workers for the same app and --parallel only if that app's project offers the same spec set on those workers.

If applications have different record keys, map the correct secret by separate jobs or environments. Never select secret names dynamically from untrusted pull request content. Repository structure does not override Cloud project identity.

7. Static GitHub Shards Without Cypress Cloud

For a small stable suite, a fixed matrix is transparent and does not require recorded orchestration. Each shard owns a feature directory.

name: Cypress manual shards

on:
  pull_request:

jobs:
  e2e:
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        include:
          - shard: account
            specs: cypress/e2e/account/**/*.cy.ts
          - shard: projects
            specs: cypress/e2e/projects/**/*.cy.ts
          - shard: reports
            specs: cypress/e2e/reports/**/*.cy.ts

    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 22
          cache: npm
      - run: npm ci
      - name: Run shard
        run: npx cypress run --spec "${{ matrix.specs }}"
      - name: Upload shard artifacts
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: cypress-${{ matrix.shard }}
          path: |
            cypress/screenshots
            cypress/videos
          if-no-files-found: ignore

Add application startup to every job or target a stable deployed environment. --spec accepts the provided glob and limits discovery to it. Ensure each spec belongs to exactly one shard, and decide whether no matching specs should fail. Cypress offers --pass-with-no-tests when an intentionally empty selection should exit successfully, but use it only with a deliberate empty-shard policy.

Static ownership is easy to review, yet it drifts as one feature grows. Track shard durations and move coherent subdirectories when imbalance becomes material. The how to use Cypress parallelization guide explains how to measure that decision.

8. Deterministic Node Sharding Script

A small script can sort discovered specs and allocate them by modulo. This is deterministic, dependency-free sharding by file count, not duration-aware balancing.

// scripts/cypress-shard.mjs
import { readdirSync } from 'node:fs'
import { join } from 'node:path'
import { spawnSync } from 'node:child_process'

const root = 'cypress/e2e'
const shardIndex = Number(process.env.SHARD_INDEX)
const shardTotal = Number(process.env.SHARD_TOTAL)

if (!Number.isInteger(shardIndex) || !Number.isInteger(shardTotal)) {
  throw new Error('SHARD_INDEX and SHARD_TOTAL must be integers')
}

if (shardIndex < 0 || shardIndex >= shardTotal || shardTotal < 1) {
  throw new Error('Shard index must be zero-based and less than total')
}

function findSpecs(directory) {
  return readdirSync(directory, { withFileTypes: true }).flatMap((entry) => {
    const path = join(directory, entry.name)
    if (entry.isDirectory()) return findSpecs(path)
    return /\.cy\.(js|jsx|ts|tsx)$/.test(entry.name) ? [path] : []
  })
}

const allSpecs = findSpecs(root).sort()
const shardSpecs = allSpecs.filter((_, index) => index % shardTotal === shardIndex)

console.log(JSON.stringify({ shardIndex, shardTotal, shardSpecs }, null, 2))

if (shardSpecs.length === 0) process.exit(0)

const result = spawnSync(
  'npx',
  ['cypress', 'run', '--spec', shardSpecs.join(',')],
  { stdio: 'inherit', shell: process.platform === 'win32' },
)

process.exit(result.status ?? 1)

Run it from a zero-based CI matrix:

SHARD_INDEX=0 SHARD_TOTAL=4 node scripts/cypress-shard.mjs

Sorting ensures every worker sees the same ordered inputs. The script prints assignments so a missing spec is diagnosable. Modulo by file count can still produce unequal durations. A mature version can read committed duration weights and use a greedy allocation algorithm, but those weights need updating and review.

Do not let two workers calculate from different working trees or spec filters. Store reporter output under a path derived from the shard index.

9. Worker-Safe Test Data Example

Expose build and worker namespaces to Cypress. In GitHub Actions, environment variables prefixed with CYPRESS_ become Cypress environment values without hardcoding them into the spec.

env:
  CYPRESS_BUILD_ID: ${{ github.run_id }}-${{ github.run_attempt }}
  CYPRESS_WORKER_ID: ${{ matrix.worker }}

Use those values in an API-assisted setup helper:

type Project = { id: string; name: string }

function createOwnedProject() {
  const buildId = Cypress.env('BUILD_ID') as string
  const workerId = Cypress.env('WORKER_ID') as string
  const suffix = Cypress._.random(100_000, 999_999)
  const name = `e2e-${buildId}-${workerId}-${suffix}`

  return cy.request<Project>({
    method: 'POST',
    url: '/test-support/projects',
    body: { name, owner: { buildId, workerId } },
  }).its('body')
}

it('edits its own project', () => {
  createOwnedProject().then((project) => {
    cy.visit(`/projects/${project.id}`)
    cy.get('input[name=name]').clear().type(`${project.name}-edited`)
    cy.contains('button', 'Save').click()
    cy.contains('Changes saved').should('be.visible')
  })
})

The server should authorize and label test-support data properly. Disable test-support routes in production. Cleanup can delete records matching the build owner after all workers finish, or each test can remove its exact ID in an idempotent after hook.

For authentication reuse on one worker, apply Cypress cy.session examples, but remember that each machine creates its own session cache.

10. Unique JUnit Reports and Merge Job

When each worker emits JUnit, give the file a unique name. Cypress CLI passes options to the configured reporter.

- name: Run Cypress with JUnit
  run: |
    npx cypress run \
      --reporter junit \
      --reporter-options "mochaFile=reports/junit-worker-${{ matrix.worker }}-[hash].xml,toConsole=true"

- name: Upload JUnit fragment
  if: always()
  uses: actions/upload-artifact@v4
  with:
    name: junit-${{ matrix.worker }}
    path: reports/*.xml
    if-no-files-found: error

[hash] prevents one spec from replacing another report generated by the same worker. A downstream job can download all fragments and merge them with the chosen JUnit tooling, or the CI platform can ingest multiple XML files directly.

Do not use a single shared filesystem path across concurrent jobs unless the storage guarantees safe unique writes. Even then, explicit worker and spec names make diagnosis easier.

The artifact upload runs with if: always(), but the Cypress step still controls job success. If a merge job publishes a report, configure its dependencies so it runs after every shard and fails when inputs are unexpectedly missing. Report merging must not convert failed Cypress exits into a successful pipeline.

11. Selective Pull Request and Nightly Topologies

Not every workflow needs the same worker count. Pull requests often prioritize quick Chrome feedback, while nightly runs add browsers, broader environments, and more recorded groups.

strategy:
  matrix:
    worker: ${{ fromJSON(github.event_name == 'schedule' && '[1,2,3,4,5,6]' || '[1,2,3]') }}

Complex expressions in CI YAML can be hard to maintain. Separate workflow files or jobs are often clearer:

  • Pull request: three Chrome end-to-end workers, two component workers.
  • Main branch: four Chrome end-to-end workers plus a smoke browser group.
  • Nightly: six Chrome workers, selected Firefox and Edge groups, and slower integration environments.

Give each group a stable descriptive name and tag the recorded run with a low-cardinality purpose. Do not change group names merely to include the worker number. Cloud needs workers of the same family to join one group.

Capacity matters. A nightly run with three browser groups can triple login calls and data creation. Confirm identity-provider, database, and application limits before expanding the matrix. If broad browser coverage is serially cheap and operationally risky in parallel, keep it deliberately smaller.

12. Complete Cypress Parallelization Example with Verification

Treat the parallel workflow like production infrastructure and add a focused verification plan. Create at least twice as many specs as workers so dynamic assignment is visible, and give one spec a controlled additional duration only in a disposable demonstration branch. Confirm that workers request multiple files and the run completes under one build and group.

Then verify failure behavior:

  1. Make one assertion fail and confirm the worker exits nonzero.
  2. Confirm sibling workers follow the selected CI and Cloud cancellation policies.
  3. Check the first failed attempt, screenshot, video, and browser metadata.
  4. Rerun the workflow and confirm the attempt gets a distinct build ID.
  5. Remove the deliberate failure and verify no stale artifact is reported.

Verify data isolation by running two copies of a mutation-heavy spec at the same time with different worker namespaces. Each should create, read, update, and delete only its own record. Inspect server logs for cross-worker IDs.

Finally, record a baseline and several parallel runs. Compare full job duration, not only Cypress test time. Include environment startup, install, browser launch, Cloud completion, report merge, and artifact upload. The most successful example is the smallest topology that meets the team's feedback target reliably.

For framework-level interview explanations, use Cypress interview questions and answers.

13. Troubleshooting Example Failures

If Cloud shows separate runs instead of one run, print the build ID and group on every worker. A worker-specific suffix in the build ID is a common mistake. Also confirm the project ID and record key target the same Cloud project.

If one worker reports a different spec set, compare the checkout revision, generated files, specPattern, environment flags, and --config values. All workers in one parallel group must offer compatible discovery. Do not use --spec to give each Cloud worker a different manual shard.

If a matrix job hangs after tests finish, inspect application background processes, reporter completion, artifact upload, and Cypress Cloud run completion behavior. Ensure shell scripts propagate signals and exit codes. A preview server launched in the background should end when the isolated CI job ends.

If failures increase with worker count, reduce concurrency to confirm the relationship, then inspect database connections, API rate limits, authentication quotas, CPU, and memory. A slower application can trigger real client timeouts. The durable response is capacity planning or test boundary isolation, not a blanket Cypress timeout increase.

If a manual shard finds no specs, verify glob quoting and the current working directory. Decide whether that is a configuration error or an allowed empty partition, and use --pass-with-no-tests only for the latter.

Interview Questions and Answers

Q: What values are shared across Cloud workers?

Workers share the build ID, group name, Cloud project, revision, spec discovery, and compatible configuration. Worker IDs and data namespaces remain unique. The record key is the same secret but is never printed.

Q: Why is the matrix worker not part of the build ID?

The build ID links workers into one run. Adding the worker makes each value different and separates the jobs. The worker belongs in artifact and test-data names instead.

Q: How do cross-browser groups work?

Each browser has a distinct group under the same recorded build. Workers with the same browser and group can parallelize that group's queue. Incompatible browsers should not share one group name.

Q: Is a static matrix load balanced?

Only if maintainers or a script assigned balanced spec sets. Fixed jobs do not request new work after finishing, so a slow shard determines completion. Cloud dynamic assignment is a different model.

Q: How do you merge reports safely?

Every worker writes uniquely named files, uploads them even on failure, and a downstream job gathers the fragments. The merge process preserves Cypress failures and treats unexpectedly missing input as an error.

Q: What does a good worker namespace contain?

It contains a traceable build identifier, a worker identifier, and a unique test suffix where needed. The backend records ownership so cleanup deletes only resources created by that worker or test.

Q: How do you test the CI configuration itself?

I verify joined workers, deliberate failure propagation, rerun identity, artifact retention, and data isolation. I then compare full pipeline duration across several representative runs before choosing worker count.

Common Mistakes

  • Including the matrix worker number in the shared Cypress build ID.
  • Reusing one group name for Chrome, Firefox, end-to-end, and component runs.
  • Supplying different --spec lists to workers in one Cloud parallel group.
  • Committing the record key in a sample workflow.
  • Copying a container tag without verifying its browser and Cypress compatibility.
  • Starting the application without a readiness check.
  • Letting worker artifacts overwrite files under one shared name.
  • Assuming modulo sharding by file count balances duration.
  • Allowing empty shards to pass without an explicit policy.
  • Reusing mutable test accounts because browser sessions are machine-local.

Conclusion

Use the Cypress parallelization example that matches your orchestration model. Cypress Cloud workers should execute the same recorded parallel command with one build ID and group, while manual shards should receive explicit, non-overlapping specs. In both cases, give every worker unique data and artifact ownership.

Start with the complete two-worker version, verify joined scheduling and failure propagation, then scale from measured wall-clock results. Keep the topology readable enough that another SDET can explain why every ID, group, worker, and report path exists.

Interview Questions and Answers

Describe a GitHub Actions Cypress parallel setup.

I use a matrix to create identical worker jobs. Each checks out the same revision, installs from the lockfile, starts and verifies the application, then runs the same recorded parallel command with one build ID and group. Worker IDs are reserved for data and artifacts.

What happens if workers use different build IDs?

Cypress cannot associate them as one parallel run, so they appear separately or fail the intended orchestration. I print non-secret identity inputs during diagnosis and remove worker-specific suffixes from the shared ID.

Why use separate groups for browser and test type?

A group represents one compatible execution family. Browser and testing-type differences affect configuration, spec sets, and duration history. Distinct names keep recorded results and scheduling coherent.

What is the tradeoff of a modulo sharding script?

It is simple, deterministic, and Cloud-independent, but it balances file count rather than actual duration. It also cannot reassign work when one job finishes early, so the slowest shard controls completion.

How do you isolate data in a matrix?

I expose the workflow build and matrix worker as non-secret Cypress environment values. Setup APIs label every record with that ownership, and cleanup removes only matching resources. Mutating flows receive distinct users or tenants.

How do you preserve failure status when uploading artifacts?

The Cypress command remains its own step and returns the test exit code. Artifact steps use an always condition so they run after failure, but they do not replace or suppress the earlier status.

How do you handle an empty manual shard?

I decide whether emptiness is expected. A calculation script can exit successfully for an intentionally empty partition, or Cypress can use --pass-with-no-tests. Unexpected emptiness should fail with printed discovery inputs.

What do you measure after implementing a parallel example?

I measure complete wall-clock duration, slowest worker, setup and artifact overhead, compute minutes, application capacity, and retry-assisted passes. Several representative runs are needed before selecting the production worker count.

Frequently Asked Questions

What is a working Cypress parallelization command?

Run npx cypress run with --record, --parallel, a group, and a shared CI build ID on every worker. Supply CYPRESS_RECORD_KEY securely and configure the Cloud project ID.

How do I parallelize Cypress in GitHub Actions?

Create a matrix with two or more worker jobs, then run the same Cloud parallel command in each. Use github.run_id plus github.run_attempt as a shared build identity and matrix.worker only for local namespacing.

How do I parallelize Cypress in GitLab CI?

Use GitLab's parallel job count to create workers and run the same recorded Cypress command in every instance. CI_NODE_INDEX is useful for data and artifact names, while the pipeline build ID stays common.

Can I use different specs on each Cypress Cloud worker?

Not within one dynamically balanced group. Workers should offer the same spec list so Cypress Cloud can assign files. Use separate groups or manual sharding for intentionally different lists.

How do I run Cypress shards without Cloud?

Create a CI matrix and pass each job an explicit glob or computed comma-separated list through --spec. Your pipeline must handle balancing, empty shards, reporting, and reruns.

How should parallel Cypress artifacts be named?

Include a worker or shard identifier in artifact names and reporter filenames. Use a hash or spec-specific token when one worker creates multiple report files.

What build ID should a rerun use?

Use a value that changes with the workflow attempt, not only the commit. In GitHub Actions, run ID plus run attempt is a practical explicit choice.

Related Guides