---
title: Automatically Split Slow Tasks by File (Atomizer)
description: Automatically split large test tasks into individual file-level tasks for parallel execution
keywords: [split tasks, atomizer]
sidebar:
  label: Automatically Split Slow Tasks
  order: 15
filter: 'type:Features'
---

{% youtube
src="https://youtu.be/0YxcxIR7QU0"
title="10x Faster e2e Tests!"
width="100%" /%}

Certain tasks like end-to-end (e2e) tests, integration tests, or large unit test suites can be large, monolithic tasks that take a considerable amount of time to execute. As a result, teams often push them to a nightly or even weekly build rather than running them for each PR. This approach is suboptimal as it increases the risk of merging problematic PRs.

Manually splitting these slow tasks can be complex and require ongoing maintenance. Nx Atomizer solves this by **automatically generating runnable targets for each test file**. For example, a task that takes 10 minutes can be split and distributed as five 2-minute tasks per agent. This allows for:

- parallelization across multiple machines with [Nx Agents](/docs/features/ci-features/distribute-task-execution)
- faster [flakiness detection & retries](/docs/features/ci-features/flaky-tasks) by isolating and re-running only the failed tests

## Enable automated task splitting

### Step 1: Connect to Nx Cloud

To use **automated task splitting**, you need to connect your workspace to Nx Cloud (if you haven't already).

```shell
npx nx@latest connect
```

See the [connect to Nx Cloud recipe](/docs/guides/nx-cloud/setup-ci) for all the details.

### Step 2: add the appropriate plugin

Run this command to set up inferred tasks and enable task splitting for each plugin:

{% tabs syncKey="test-runner" %}
{% tabitem label="Cypress" %}

```shell
nx add @nx/cypress
```

{% /tabitem %}
{% tabitem label="Playwright" %}

```shell
nx add @nx/playwright
```

{% /tabitem %}
{% tabitem label="Jest" %}

```shell
nx add @nx/jest
```

{% /tabitem %}
{% tabitem label="Vitest" %}

```shell
nx add @nx/vitest
```

{% /tabitem %}
{% tabitem label="Gradle" %}

```shell
nx add @nx/gradle
```

{% /tabitem %}
{% /tabs %}

This command will register the appropriate plugin in the `plugins` array of `nx.json`.

If you upgraded Nx from an older version, ensure that [inferred tasks](/docs/concepts/inferred-tasks#existing-nx-workspaces) are enabled in `nx.json`:

```json
// nx.json
{
  ...
  // turned on by default; just make sure it is not set to false
  useInferencePlugins: true
}
```

## Update an existing project to use automated task splitting

If you are already using the `@nx/cypress`, `@nx/playwright`, `@nx/jest`, `@nx/vitest`, or `@nx/gradle` plugin, you need to manually add the appropriate configuration to the `plugins` array of `nx.json`. Follow the instructions for the plugin you are using:

- [Configure Cypress Task Splitting](/docs/technologies/test-tools/cypress/introduction#nxcypress-configuration)
- [Configure Playwright Task Splitting](/docs/technologies/test-tools/playwright/introduction#nxplaywright-configuration)
- [Configure Jest Task Splitting](/docs/technologies/test-tools/jest/introduction#splitting-e2e-tests)
- [Configure Vitest Task Splitting](/docs/technologies/test-tools/vitest/introduction#splitting-e2e-tests)
- [Configure Gradle Testing Task Splitting](/docs/technologies/java/gradle/introduction#test-distribution)

## Verify automated task splitting works

Run the following command to open the project detail view for your test project:

{% tabs %}
{% tabitem label="CLI" %}

```shell
nx show project my-project-e2e
```

{% /tabitem %}
{% tabitem label="Project Detail View" %}

{% project_details title="Project Details View" %}

```json
{
  "project": {
    "name": "admin-e2e",
    "data": {
      "metadata": {
        "targetGroups": {
          "E2E (CI)": [
            "e2e-ci--src/e2e/app.cy.ts",
            "e2e-ci--src/e2e/login.cy.ts",
            "e2e-ci"
          ]
        }
      },
      "root": "apps/admin-e2e",
      "projectType": "application",
      "targets": {
        "e2e": {
          "cache": true,
          "inputs": ["default", "^production"],
          "outputs": [
            "{workspaceRoot}/dist/cypress/apps/admin-e2e/videos",
            "{workspaceRoot}/dist/cypress/apps/admin-e2e/screenshots"
          ],
          "executor": "nx:run-commands",
          "dependsOn": ["^build"],
          "options": {
            "cwd": "apps/admin-e2e",
            "command": "cypress run"
          },
          "configurations": {
            "production": {
              "command": "cypress run --env webServerCommand=\"nx run admin:preview\""
            }
          },
          "metadata": {
            "technologies": ["cypress"]
          }
        },
        "e2e-ci--src/e2e/app.cy.ts": {
          "outputs": [
            "{workspaceRoot}/dist/cypress/apps/admin-e2e/videos",
            "{workspaceRoot}/dist/cypress/apps/admin-e2e/screenshots"
          ],
          "inputs": [
            "default",
            "^production",
            {
              "externalDependencies": ["cypress"]
            }
          ],
          "cache": true,
          "options": {
            "cwd": "apps/admin-e2e",
            "command": "cypress run --env webServerCommand=\"nx run admin:serve-static\" --spec src/e2e/app.cy.ts"
          },
          "executor": "nx:run-commands",
          "configurations": {},
          "metadata": {
            "technologies": ["cypress"]
          }
        },
        "e2e-ci--src/e2e/login.cy.ts": {
          "outputs": [
            "{workspaceRoot}/dist/cypress/apps/admin-e2e/videos",
            "{workspaceRoot}/dist/cypress/apps/admin-e2e/screenshots"
          ],
          "inputs": [
            "default",
            "^production",
            {
              "externalDependencies": ["cypress"]
            }
          ],
          "cache": true,
          "options": {
            "cwd": "apps/admin-e2e",
            "command": "cypress run --env webServerCommand=\"nx run admin:serve-static\" --spec src/e2e/login.cy.ts"
          },
          "executor": "nx:run-commands",
          "configurations": {},
          "metadata": {
            "technologies": ["cypress"]
          }
        },
        "e2e-ci": {
          "executor": "nx:noop",
          "cache": true,
          "inputs": [
            "default",
            "^production",
            {
              "externalDependencies": ["cypress"]
            }
          ],
          "outputs": [
            "{workspaceRoot}/dist/cypress/apps/admin-e2e/videos",
            "{workspaceRoot}/dist/cypress/apps/admin-e2e/screenshots"
          ],
          "dependsOn": [
            {
              "target": "e2e-ci--src/e2e/app.cy.ts",
              "projects": "self",
              "params": "forward",
              "options": "forward"
            },
            {
              "target": "e2e-ci--src/e2e/login.cy.ts",
              "projects": "self",
              "params": "forward",
              "options": "forward"
            }
          ],
          "options": {},
          "configurations": {},
          "metadata": {
            "technologies": ["cypress"]
          }
        },
        "lint": {
          "executor": "@nx/eslint:lint",
          "inputs": ["default", "{workspaceRoot}/.eslintrc.json"],
          "cache": true,
          "outputs": ["{options.outputFile}"],
          "options": {},
          "configurations": {},
          "metadata": {
            "technologies": ["eslint"]
          }
        }
      },
      "name": "admin-e2e",
      "$schema": "../../node_modules/nx/schemas/project-schema.json",
      "sourceRoot": "apps/admin-e2e/src",
      "tags": [],
      "implicitDependencies": ["admin"]
    }
  },
  "sourceMap": {
    "root": ["apps/admin-e2e/project.json", "nx/core/project-json"],
    "projectType": ["apps/admin-e2e/project.json", "nx/core/project-json"],
    "targets": ["apps/admin-e2e/project.json", "nx/core/project-json"],
    "targets.e2e": ["apps/admin-e2e/project.json", "nx/core/target-defaults"],
    "targets.e2e.options": [
      "apps/admin-e2e/cypress.config.ts",
      "@nx/cypress/plugin"
    ],
    "targets.e2e.cache": [
      "apps/admin-e2e/project.json",
      "nx/core/target-defaults"
    ],
    "targets.e2e.inputs": [
      "apps/admin-e2e/project.json",
      "nx/core/target-defaults"
    ],
    "targets.e2e.outputs": [
      "apps/admin-e2e/cypress.config.ts",
      "@nx/cypress/plugin"
    ],
    "targets.e2e.configurations": [
      "apps/admin-e2e/cypress.config.ts",
      "@nx/cypress/plugin"
    ],
    "targets.e2e.executor": [
      "apps/admin-e2e/cypress.config.ts",
      "@nx/cypress/plugin"
    ],
    "targets.e2e.options.cwd": [
      "apps/admin-e2e/cypress.config.ts",
      "@nx/cypress/plugin"
    ],
    "targets.e2e.options.command": [
      "apps/admin-e2e/cypress.config.ts",
      "@nx/cypress/plugin"
    ],
    "targets.e2e.configurations.production": [
      "apps/admin-e2e/cypress.config.ts",
      "@nx/cypress/plugin"
    ],
    "targets.e2e.configurations.production.command": [
      "apps/admin-e2e/cypress.config.ts",
      "@nx/cypress/plugin"
    ],
    "targets.e2e-ci--src/e2e/app.cy.ts": [
      "apps/admin-e2e/cypress.config.ts",
      "@nx/cypress/plugin"
    ],
    "targets.e2e-ci--src/e2e/app.cy.ts.outputs": [
      "apps/admin-e2e/cypress.config.ts",
      "@nx/cypress/plugin"
    ],
    "targets.e2e-ci--src/e2e/app.cy.ts.inputs": [
      "apps/admin-e2e/cypress.config.ts",
      "@nx/cypress/plugin"
    ],
    "targets.e2e-ci--src/e2e/app.cy.ts.cache": [
      "apps/admin-e2e/cypress.config.ts",
      "@nx/cypress/plugin"
    ],
    "targets.e2e-ci--src/e2e/app.cy.ts.options": [
      "apps/admin-e2e/cypress.config.ts",
      "@nx/cypress/plugin"
    ],
    "targets.e2e-ci--src/e2e/app.cy.ts.executor": [
      "apps/admin-e2e/cypress.config.ts",
      "@nx/cypress/plugin"
    ],
    "targets.e2e-ci--src/e2e/app.cy.ts.options.cwd": [
      "apps/admin-e2e/cypress.config.ts",
      "@nx/cypress/plugin"
    ],
    "targets.e2e-ci--src/e2e/app.cy.ts.options.command": [
      "apps/admin-e2e/cypress.config.ts",
      "@nx/cypress/plugin"
    ],
    "targets.e2e-ci--src/e2e/login.cy.ts": [
      "apps/admin-e2e/cypress.config.ts",
      "@nx/cypress/plugin"
    ],
    "targets.e2e-ci--src/e2e/login.cy.ts.outputs": [
      "apps/admin-e2e/cypress.config.ts",
      "@nx/cypress/plugin"
    ],
    "targets.e2e-ci--src/e2e/login.cy.ts.inputs": [
      "apps/admin-e2e/cypress.config.ts",
      "@nx/cypress/plugin"
    ],
    "targets.e2e-ci--src/e2e/login.cy.ts.cache": [
      "apps/admin-e2e/cypress.config.ts",
      "@nx/cypress/plugin"
    ],
    "targets.e2e-ci--src/e2e/login.cy.ts.options": [
      "apps/admin-e2e/cypress.config.ts",
      "@nx/cypress/plugin"
    ],
    "targets.e2e-ci--src/e2e/login.cy.ts.executor": [
      "apps/admin-e2e/cypress.config.ts",
      "@nx/cypress/plugin"
    ],
    "targets.e2e-ci--src/e2e/login.cy.ts.options.cwd": [
      "apps/admin-e2e/cypress.config.ts",
      "@nx/cypress/plugin"
    ],
    "targets.e2e-ci--src/e2e/login.cy.ts.options.command": [
      "apps/admin-e2e/cypress.config.ts",
      "@nx/cypress/plugin"
    ],
    "targets.e2e-ci": [
      "apps/admin-e2e/cypress.config.ts",
      "@nx/cypress/plugin"
    ],
    "targets.e2e-ci.executor": [
      "apps/admin-e2e/cypress.config.ts",
      "@nx/cypress/plugin"
    ],
    "targets.e2e-ci.cache": [
      "apps/admin-e2e/cypress.config.ts",
      "@nx/cypress/plugin"
    ],
    "targets.e2e-ci.inputs": [
      "apps/admin-e2e/cypress.config.ts",
      "@nx/cypress/plugin"
    ],
    "targets.e2e-ci.outputs": [
      "apps/admin-e2e/cypress.config.ts",
      "@nx/cypress/plugin"
    ],
    "targets.e2e-ci.dependsOn": [
      "apps/admin-e2e/cypress.config.ts",
      "@nx/cypress/plugin"
    ],
    "targets.e2e.dependsOn": [
      "apps/admin-e2e/project.json",
      "nx/core/target-defaults"
    ],
    "targets.lint": ["apps/admin-e2e/project.json", "nx/core/project-json"],
    "targets.lint.executor": [
      "apps/admin-e2e/project.json",
      "nx/core/project-json"
    ],
    "targets.lint.inputs": [
      "apps/admin-e2e/project.json",
      "nx/core/target-defaults"
    ],
    "targets.lint.cache": [
      "apps/admin-e2e/project.json",
      "nx/core/target-defaults"
    ],
    "name": ["apps/admin-e2e/project.json", "nx/core/project-json"],
    "$schema": ["apps/admin-e2e/project.json", "nx/core/project-json"],
    "sourceRoot": ["apps/admin-e2e/project.json", "nx/core/project-json"],
    "tags": ["apps/admin-e2e/project.json", "nx/core/project-json"],
    "implicitDependencies": [
      "apps/admin-e2e/project.json",
      "nx/core/project-json"
    ],
    "implicitDependencies.admin": [
      "apps/admin-e2e/project.json",
      "nx/core/project-json"
    ],
    "targets.lint.outputs": [
      "apps/admin-e2e/project.json",
      "nx/core/project-json"
    ]
  }
}
```

{% /project_details %}

{% /tabitem %}
{% /tabs %}

If you configured Nx Atomizer properly, you'll see that there are tasks named `e2e`, `e2e-ci` (or similar for other test types) and a task for each test file.

During local development, you'll want to continue using the base task (e.g., `e2e`, `test`) as it is more efficient on a single machine.

```shell
nx e2e my-project-e2e
```

The `-ci` variant task truly shines when configured and run on CI.

## Configure automated task splitting on CI

Update your CI pipeline to run the `-ci` variant task (e.g., `e2e-ci`, `test-ci`), which will automatically run all the inferred tasks for the individual test files. Here's an example of a GitHub Actions workflow:

```yaml {% meta="{17,27}" %}
// .github/workflows/ci.yml
name: CI
# ...
jobs:
  main:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
          filter: tree:0

      - uses: pnpm/action-setup@v4
        with:
          version: 9

      - run: pnpm dlx nx start-ci-run --distribute-on="3 linux-medium-js" --stop-agents-after="e2e-ci"

      - uses: actions/setup-node@v3
        with:
          node-version: 20
          cache: 'pnpm'

      - run: pnpm install --frozen-lockfile
      - uses: nrwl/nx-set-shas@v5

      - run: pnpm exec nx affected -t lint test build e2e-ci
```

Learn more about configuring your [CI provider by following these detailed recipes](/docs/guides/nx-cloud/setup-ci).
