Migrating from ESLint and Prettier to Biome for 30x Faster CI Builds

A production engineering playbook for migrating large JavaScript and TypeScript codebases from ESLint and Prettier to Biome for 30x faster CI builds.

Mahmudul Haque Qudrati — CEO & ML Engineer at Pristren

Mahmudul Haque Qudrati

CEO & ML Engineer

May 4, 2026
7 min read
Migrating from ESLint and Prettier to Biome for 30x Faster CI Builds

In any sufficiently large TypeScript monorepo, continuous integration pipelines inevitably slow down, which is why migrating from ESLint to Biome has become a popular fix.

A developer pushes a one-line bug fix. Before automated tests can even begin, the pull request validation job spends three minutes running Node.js linting and formatting checks. The runner pulls in over 30 separate npm packages - eslint, prettier, @typescript-eslint/parser, @typescript-eslint/eslint-plugin, eslint-plugin-react-hooks, eslint-plugin-import, and eslint-config-prettier - consuming gigabytes of memory and generating thousands of CPU cycles just parsing JavaScript code through JavaScript.

Compounding the performance tax is friction between tools. Developers spend countless hours resolving conflicts where Prettier formats code one way, and an ESLint stylistic rule flags that exact format as a lint error.

This tooling fatigue has accelerated a major industry shift: migrating from ESLint to Biome.

Originally conceived as Rome, Biome is a fast, Rust-powered unified toolchain for the web. By replacing two distinct Node.js tools with a single native binary that formats and lints in a single pass, Biome slashes CI check times by over 90% while radically simplifying developer configuration.

In this guide, we break down the architectural differences between Node-based linters and unified Rust tools, evaluate feature parity, and provide a step-by-step migration blueprint for production repositories.


The Architectural Flaw in Legacy JavaScript Toolchains: Why Migrating from ESLint to Biome Matters

To understand why Biome is so much faster than ESLint and Prettier, consider how traditional tooling processes your source files:

snippet
LEGACY TOOLCHAIN (3 Traversal Passes in Node.js):
File.tsx ──> [Node.js Engine] ──> Parses AST #1 ──> Runs Prettier Formatter
         ──> [Node.js Engine] ──> Parses AST #2 ──> Runs ESLint Core Rules
         ──> [Node.js Engine] ──> Parses AST #3 ──> Runs TypeScript-ESLint Typechecked Rules
Total Time: 120 - 180 seconds | Memory: ~1.8 GB RAM

BIOME ARCHITECTURE (1 Traversal Pass in Native Rust):
File.tsx ──> [Rust Native Binary] ──> Parses Unified AST Once ──> Formats + Lints + Sorts Imports
Total Time: 2 - 4 seconds | Memory: ~85 MB RAM
  1. Redundant AST Parsing: In a standard setup, Prettier reads the file from disk, parses it into an Abstract Syntax Tree (AST), formats it, and prints it. Then ESLint reads the same file from disk, parses it into another AST, runs lint rules, and outputs errors. TypeScript-ESLint often parses the file a third time.
  2. Node.js Runtime Overhead: ESLint and Prettier are interpreted JavaScript executing inside the V8 engine. They suffer from garbage collection pauses, single-threaded execution bottlenecks, and slow module resolution.
  3. Single Unified AST: Biome is compiled directly to native machine code in Rust. It reads the file once, constructs a single high-performance CST (Concrete Syntax Tree), and evaluates formatting, linting, and import sorting simultaneously in parallel across all available CPU cores.

Feature Parity: What Biome Replaces

Before migrating an enterprise codebase, engineering teams need to verify whether Biome covers their existing rule sets.

Tooling CapabilityLegacy Node StackBiome EquivalentCoverage Status
Code FormattingPrettierBiome Formatter97%+ Compatibility (identical style defaults)
Import Sortingeslint-plugin-import + prettier-plugin-sort-importsNative Import OrganizerBuilt-in (zero config required)
TypeScript Linting@typescript-eslint/eslint-pluginBiome TypeScript RulesFull Support for syntax & style rules
React & Hookseslint-plugin-react + eslint-plugin-react-hooksBiome Nursery & RecommendedFull Support (exhaustive deps, rules of hooks)
Next.js Rules@next/eslint-plugin-nextBiome Next.js Recommended RulesSupported (core image, script, link rules)
Bespoke AST PluginsCustom internal ESLint pluginsCustom Rust lint rules (in development)Partial (requires Biome plugin API maturity)

For modern frameworks like Next.js 15, Vite, or Remix, Biome provides drop-in coverage for virtually all standard linting and formatting requirements. For teams modernizing their full stack, pairing Biome with a streamlined framework like Next.js 15 architecture ensures blazing-fast local iterations.


Step-by-Step Migration Blueprint

Migrating an existing TypeScript codebase from ESLint and Prettier to Biome takes less than thirty minutes when following this protocol:

Step 1: Install Biome and Run the Automated Migration Utility

First, install Biome as a development dependency:

bash
# Using pnpm
pnpm add --save-dev --save-exact @biomejs/biome

# Using npm
npm install --save-dev --save-exact @biomejs/biome

Next, leverage Biome's native migration engine to inspect your existing .eslintrc or eslint.config.js file and automatically generate a corresponding configuration:

bash
npx @biomejs/biome migrate eslint --write

This command reads your active ESLint configuration, maps supported rules to Biome equivalents, sets severity levels, and writes a clean biome.json file to the project root.


Step 2: Production-Hardened biome.json Configuration

Below is a production-grade biome.json manifest tailored for enterprise TypeScript and React applications:

json
{
  "$schema": "https://biomejs.dev/schemas/1.9.4/schema.json",
  "vcs": {
    "enabled": true,
    "clientKind": "git",
    "useIgnoreFile": true
  },
  "files": {
    "ignoreUnknown": true,
    "ignore": ["node_modules", ".next", "dist", "build", "coverage", "public"]
  },
  "formatter": {
    "enabled": true,
    "formatWithErrors": false,
    "indentStyle": "space",
    "indentWidth": 2,
    "lineEnding": "lf",
    "lineWidth": 100
  },
  "javascript": {
    "formatter": {
      "quoteStyle": "double",
      "jsxQuoteStyle": "double",
      "semicolons": "always",
      "trailingCommas": "es5",
      "arrowParentheses": "always"
    }
  },
  "linter": {
    "enabled": true,
    "rules": {
      "recommended": true,
      "complexity": {
        "noExcessiveCognitiveComplexity": "warn",
        "noVoid": "error"
      },
      "correctness": {
        "noUnusedVariables": "error",
        "noUnusedImports": "error",
        "useHookAtTopLevel": "error"
      },
      "style": {
        "useConst": "error",
        "useTemplate": "error",
        "noNonNullAssertion": "warn"
      },
      "suspicious": {
        "noExplicitAny": "warn",
        "noConsole": "warn"
      }
    }
  },
  "organizeImports": {
    "enabled": true
  }
}

Notice the organizeImports configuration. With Biome, you no longer need complex import sorting plugins; Biome automatically clusters external libraries, internal path aliases, and relative imports upon save.


Step 3: Purging Outdated Node Dependencies

Once Biome is active, you can eliminate an entire category of bloat from your package.json. In our production tests, migrating from ESLint to Biome typically drops between 20 and 45 devDependencies:

bash
# Remove legacy formatting and linting dependencies
pnpm remove   eslint   prettier   @typescript-eslint/parser   @typescript-eslint/eslint-plugin   eslint-config-prettier   eslint-plugin-prettier   eslint-plugin-react   eslint-plugin-react-hooks   eslint-plugin-import

Delete legacy config files:

bash
rm -f .eslintrc* .prettierrc* .eslintignore .prettierignore

Step 4: Updating NPM Scripts and Pre-Commit Hooks

Update the scripts section of your package.json:

json
{
  "scripts": {
    "lint": "biome check .",
    "lint:fix": "biome check --write .",
    "format": "biome format --write .",
    "check": "biome check --write --unsafe ."
  }
}

Integrating with Pre-Commit Hooks (Lefthook / Husky)

Because Biome processes thousands of lines in milliseconds, pre-commit hooks complete almost instantaneously without frustrating developers:

yaml
# lefthook.yml
pre-commit:
  parallel: true
  commands:
    biome-check:
      glob: "*.{js,ts,jsx,tsx,json}"
      run: npx @biomejs/biome check --write --no-errors-on-unmatched {staged_files}
      stage_fixed: true

Continuous Integration Workflow: GitHub Actions

In continuous integration environments, Biome integrates directly with GitHub annotations, highlighting linting errors inline on pull request diffs:

yaml
name: Code Quality Check

on:
  pull_request:
    branches: [main, develop]
  push:
    branches: [main]

jobs:
  quality:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout Repository
        uses: actions/checkout@v4

      - name: Setup Biome Toolchain
        uses: biomejs/setup-biome@v2
        with:
          version: latest

      - name: Run Biome Verification
        run: biome ci --reporter=github .

The --reporter=github flag automatically converts Biome diagnostics into native GitHub Checks annotations on pull requests without requiring third-party action wrappers.


Real-World Production Benchmarks

To quantify the impact of migrating from ESLint to Biome, we measured execution times across an enterprise monorepo comprising 120,000 lines of TypeScript and React code:

snippet
┌─────────────────────────────────┬─────────────────┬─────────────────┐
│ BENCHMARK METRIC                │ ESLINT + PRETTIER│ BIOME RUNNER    │
├─────────────────────────────────┼─────────────────┼─────────────────┤
│ Full Monorepo Format Check      │ 48.2 seconds    │ 0.9 seconds     │
│ Full Monorepo Lint Verification │ 94.1 seconds    │ 2.9 seconds     │
│ Combined CI Quality Job         │ 142.3 seconds   │ 3.8 seconds     │
│ Pre-Commit Git Hook Delay       │ 14.8 seconds    │ 0.2 seconds     │
│ Peak Memory Consumption (RAM)  │ 1,840 MB        │ 88 MB           │
│ NPM Dependencies in Lockfile    │ 34 packages     │ 1 package       │
└─────────────────────────────────┴─────────────────┴─────────────────┘

The Developer Experience Payoff

Slashing combined CI lint and format validation from 142 seconds down to 3.8 seconds fundamentally changes developer momentum. When pull request feedback is near-instantaneous, code reviews accelerate, merge conflicts decrease, and developer satisfaction rises.


Modernizing Enterprise Development Workflows

Migrating large monorepos with hundreds of developers requires careful planning around rule parity, IDE extensions (VS Code, Cursor, WebStorm), and legacy exclusion boundaries.

While small codebases can execute the transition in minutes, enterprise organizations managing complex multi-team micro-frontends benefit from structured migration roadmaps that prevent merge friction and preserve team velocity.

If your engineering organization is looking to streamline developer toolchains, modernize CI/CD infrastructure, or refactor legacy monorepos for maximum performance, explore our engineering services in Complete Business Solutions or schedule a technical discussion with our team.


Production Migration Checklist for Biome

Before cutting over your team's primary CI pipelines to Biome, verify that your repository satisfies this transition checklist:

  • Automated Rule Extraction: Did you execute biome migrate eslint to import existing rule preferences?
  • Formatter Style Matching: Are quote styles, indent sizes, and line lengths aligned with your team's visual standards?
  • Dependency Pruning: Have redundant ESLint and Prettier dependencies been removed from package.json?
  • IDE Plugin Installation: Does your team have the official Biome extension installed in VS Code or Cursor?
  • CI GitHub Reporter: Is your CI pipeline configured with biome ci --reporter=github for inline PR feedback?
  • Pre-Commit Hook Optimization: Are staged files validated using Biome inside Lefthook or Husky?

Frequently Asked Questions

Can Biome completely replace both ESLint and Prettier?

For the vast majority of modern TypeScript and JavaScript codebases, yes. Biome provides native formatting with 97%+ Prettier compatibility and lints over 200 essential rules out of the box, including TypeScript checks, React hooks validation, and automated import sorting. Unless your project relies heavily on bespoke internal AST plugins or non-standard experimental syntax, Biome completely replaces both tools and drops dozens of dependencies.

How much faster is Biome compared to ESLint and Prettier?

Biome is written in Rust and uses a single unified Abstract Syntax Tree (AST) to both parse, format, and lint code in a single traversal pass. In production benchmarks across monorepos with 100,000+ lines of code, Biome processes the entire repository in 1.5 to 4 seconds - delivering a 25x to 35x speedup compared to standard Node.js-based ESLint and Prettier pipelines that take 90 to 180 seconds.

Does Biome support TypeScript, JSX, and Next.js out of the box?

Yes. Biome natively parses TypeScript, JSX, TSX, and modern ECMAScript without requiring external plugins, Babel configs, or @typescript-eslint parser bridges. It automatically provides rules for React, Next.js, and popular modern web frameworks without configuration overhead.

How do you migrate existing ESLint ignore patterns and rules to Biome?

Biome includes an automated migration CLI utility. By running 'npx @biomejs/biome migrate eslint', Biome automatically inspects your .eslintrc or eslint.config.js file, converts supported rule configurations into equivalent biome.json directives, and translates .eslintignore files into Biome ignore patterns.

#biome#eslint#prettier#code-quality#devops#ci/cd#typescript#javascript

One AI engineering post, weekly

LLM benchmarks, prompt techniques, and token-cost breakdowns, delivered to your inbox.

Comments

Have a question or something to add? Sign in to join the discussion.

Mahmudul Haque Qudrati — CEO & ML Engineer at Pristren

Mahmudul Haque Qudrati

CEO & ML Engineer

Visionary technologist, software engineer, and machine learning specialist. Founder and CEO of Pristren, directing engineering teams that ship production-grade AI/ML pipelines, mission-critical full-stack applications, and developer tooling. Creator of Zlyqor, the unified team workspace platform. Author of 540+ technical guides and benchmark research reports on large language models, agentic workflows, Model Context Protocol (MCP), and modern web stacks.

PristrenZlyqor