Skip to content

Parallel Builds

Split your visual tests across multiple machines or processes. All shards contribute screenshots to a single build.

How It Works

Give multiple test runs the same parallel-id. Vizzly groups their screenshots into one build.

The first shard creates the build. Subsequent shards with the same parallel-id add their screenshots to that build. When all shards finish, you call finalize to process comparisons.

flowchart LR A[Shard 1] --> D[Same Build] B[Shard 2] --> D C[Shard 3] --> D D --> E[vizzly finalize]

Important: Each parallel-id must be unique per build. Reusing a parallel-id after finalization adds screenshots to the existing build instead of creating a new one.

Basic Usage

Use the same parallel-id across all shards:

Terminal window
# Shard 1
vizzly run "npm test -- --shard=1/3" --parallel-id "build-12345"
# Shard 2
vizzly run "npm test -- --shard=2/3" --parallel-id "build-12345"
# Shard 3
vizzly run "npm test -- --shard=3/3" --parallel-id "build-12345"
# After all shards complete
vizzly finalize "build-12345"

You can also set VIZZLY_PARALLEL_ID instead of using the flag.

CI Examples

GitHub Actions

Use github.run_id and github.run_attempt to create a unique ID for each workflow run:

jobs:
visual-tests:
strategy:
matrix:
shard: [1/4, 2/4, 3/4, 4/4]
steps:
- name: Run visual tests
run: |
npx vizzly run "npm test -- --shard=${{ matrix.shard }}" \
--parallel-id="${{ github.run_id }}-${{ github.run_attempt }}"
env:
VIZZLY_TOKEN: ${{ secrets.VIZZLY_TOKEN }}
finalize-build:
needs: visual-tests
if: always()
steps:
- name: Finalize build
run: npx vizzly finalize "${{ github.run_id }}-${{ github.run_attempt }}"
env:
VIZZLY_TOKEN: ${{ secrets.VIZZLY_TOKEN }}

Note the if: always() on the finalize job. This runs finalization even if tests fail, which is critical for seeing your visual test results.

GitLab CI

GitLab provides CI_PIPELINE_ID which is unique per pipeline:

visual_tests:
parallel: 4
script:
- |
npx vizzly run "npm test -- --shard=${CI_NODE_INDEX}/${CI_NODE_TOTAL}" \
--parallel-id="${CI_PIPELINE_ID}"
variables:
VIZZLY_TOKEN: $VIZZLY_TOKEN
finalize_build:
needs: [visual_tests]
when: always
script:
- npx vizzly finalize "${CI_PIPELINE_ID}"
variables:
VIZZLY_TOKEN: $VIZZLY_TOKEN

CircleCI

CircleCI’s CIRCLE_WORKFLOW_ID uniquely identifies each workflow:

jobs:
visual-tests:
parallelism: 4
steps:
- run:
name: Run visual tests
command: |
npx vizzly run "npm test -- --shard=${CIRCLE_NODE_INDEX}/${CIRCLE_NODE_TOTAL}" \
--parallel-id="${CIRCLE_WORKFLOW_ID}"
environment:
VIZZLY_TOKEN: $VIZZLY_TOKEN
finalize-build:
steps:
- run: npx vizzly finalize "${CIRCLE_WORKFLOW_ID}"
environment:
VIZZLY_TOKEN: $VIZZLY_TOKEN
workflows:
visual-testing:
jobs:
- visual-tests
- finalize-build:
requires: [visual-tests]

Test Framework Integration

Playwright

Playwright has built-in sharding:

Terminal window
npx vizzly run "npx playwright test --shard=1/4" --parallel-id="build-123"
npx vizzly run "npx playwright test --shard=2/4" --parallel-id="build-123"
npx vizzly run "npx playwright test --shard=3/4" --parallel-id="build-123"
npx vizzly run "npx playwright test --shard=4/4" --parallel-id="build-123"

Jest

Split by test file patterns or directories:

Terminal window
npx vizzly run "npx jest tests/visual/components" --parallel-id="build-123"
npx vizzly run "npx jest tests/visual/pages" --parallel-id="build-123"

What Happens Without Finalize

If you don’t call finalize, your build stays in created status. Vizzly won’t process comparisons or update GitHub PR checks.

The build exists and you can see uploaded screenshots, but you won’t get pass/fail results.

Finalize Behavior

The finalize command finds the build with the given parallel-id and transitions it to completed status. This triggers:

  • Screenshot comparisons
  • GitHub PR status checks
  • Build review workflows (if enabled)

You can only finalize once. Calling finalize on an already-completed build does nothing.

Common Mistakes

Reusing parallel IDs across builds: Each build needs a unique parallel-id. If you reuse an ID from a previous build, new screenshots get added to the old build instead of creating a new one.

Terminal window
# Bad - same ID for different commits
vizzly run "npm test" --parallel-id="my-tests"
# Good - unique ID per build
vizzly run "npm test" --parallel-id="build-${COMMIT_SHA}"

Not finalizing when shards fail: Always finalize, even if some shards fail. Use if: always() in GitHub Actions or when: always in GitLab CI.

Forgetting the API token on finalize: The finalize command needs VIZZLY_TOKEN just like run does.

Next Steps