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:
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
- 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.
- 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.
- 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 Capability | Legacy Node Stack | Biome Equivalent | Coverage Status |
|---|---|---|---|
| Code Formatting | Prettier | Biome Formatter | 97%+ Compatibility (identical style defaults) |
| Import Sorting | eslint-plugin-import + prettier-plugin-sort-imports | Native Import Organizer | Built-in (zero config required) |
| TypeScript Linting | @typescript-eslint/eslint-plugin | Biome TypeScript Rules | Full Support for syntax & style rules |
| React & Hooks | eslint-plugin-react + eslint-plugin-react-hooks | Biome Nursery & Recommended | Full Support (exhaustive deps, rules of hooks) |
| Next.js Rules | @next/eslint-plugin-next | Biome Next.js Recommended Rules | Supported (core image, script, link rules) |
| Bespoke AST Plugins | Custom internal ESLint plugins | Custom 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:
# 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:
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:
{
"$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:
# 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:
rm -f .eslintrc* .prettierrc* .eslintignore .prettierignore
Step 4: Updating NPM Scripts and Pre-Commit Hooks
Update the scripts section of your package.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:
# 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:
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:
┌─────────────────────────────────┬─────────────────┬─────────────────┐
│ 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 eslintto 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=githubfor inline PR feedback? - Pre-Commit Hook Optimization: Are staged files validated using Biome inside Lefthook or Husky?

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