Biome v2 shipped in early 2026 with first-class CSS and GraphQL linting, a stable plugin API, and a single binary that replaces ESLint, Prettier, and import sorting. ESLint 9 countered with a flat config overhaul and language-agnostic plugin system. If you are choosing between them — or planning a migration — this guide covers the real trade-offs, benchmarks, and a step-by-step migration path.
.eslintrc to biome.json instantly — 100+ rule mappings, formatter extraction, and migration guidance included.What Biome and ESLint Actually Do
ESLint is a JavaScript/TypeScript linter. It analyzes your code for bugs, style violations, and best-practice issues using a plugin ecosystem. It does not format code — you need Prettier (or a similar tool) for that. A typical ESLint setup involves ESLint itself, Prettier, eslint-config-prettier to disable conflicting rules, and often 3-5 additional plugins (@typescript-eslint, eslint-plugin-react, eslint-plugin-import, etc.).
Biome is a single Rust binary that handles linting, formatting, and import sorting out of the box. One dependency. One config file. No plugin compatibility matrix to manage. It supports JavaScript, TypeScript, JSX, TSX, JSON, JSONC, CSS, and GraphQL (as of v2).
Head-to-Head Comparison
| Feature | ESLint 9 | Biome v2 |
|---|---|---|
| Language | JavaScript (Node.js) | Rust (native binary) |
| Linting | JS/TS + plugins for React, Vue, Angular, etc. | JS/TS/JSX/CSS/GraphQL built-in, 280+ rules |
| Formatting | No (needs Prettier) | Built-in, Prettier-compatible |
| Import sorting | Via eslint-plugin-import | Built-in |
| Config format | eslint.config.js (flat config) | biome.json (JSON) |
| Speed | Baseline | 20-100x faster (Rust) |
| Dependencies | 50-200+ (ESLint + plugins + Prettier) | 1 (single binary) |
| Plugin ecosystem | Massive (2,800+ plugins on npm) | Growing (plugin API stable in v2) |
| Editor support | Excellent (every editor) | VS Code, IntelliJ, Zed, Neovim |
| Vue/Svelte/Angular | Full support via plugins | Partial (HTML embedded scripts not yet) |
Performance: How Much Faster Is Biome?
Biome is written in Rust and runs as a native binary. It does not start a Node.js process, does not load plugins through JavaScript, and processes files in parallel by default. In real-world projects, Biome typically lints and formats 20-100x faster than ESLint + Prettier combined.
On a 1,000-file TypeScript monorepo, a typical ESLint + Prettier run takes 15-30 seconds. Biome finishes the same check in under 500ms. The difference is most visible in CI pipelines and pre-commit hooks, where tool startup time dominates.
# ESLint + Prettier
$ time npx eslint . && npx prettier --check .
real 0m24.3s
# Biome
$ time npx @biomejs/biome check .
real 0m0.4sWhen to Stay on ESLint
ESLint is still the right choice in several situations:
- Vue, Svelte, or Angular projects. Biome does not yet lint code inside
.vue,.svelte, or Angular template files. ESLint with framework-specific plugins is still required here. - You rely on niche ESLint plugins. If your project depends on plugins like
eslint-plugin-security,eslint-plugin-testing-library, or domain-specific rules, check whether Biome covers those rules before switching. - Custom ESLint rules. If you have written custom AST-based ESLint rules specific to your codebase, migrating them to Biome's plugin system requires rewriting in GritQL or Rust.
- Large team with established ESLint configs. If your team has invested heavily in a shared ESLint config package used across dozens of repos, the migration cost may outweigh the performance gains — at least until Biome's plugin ecosystem catches up.
When to Switch to Biome
Biome is the better choice if:
- You are starting a new project. There is no reason to set up ESLint + Prettier + 5 plugins when Biome does it all with one dependency and one config file.
- CI is slow because of linting. If ESLint + Prettier takes more than a few seconds in your pipeline, Biome will cut that to near-zero.
- You want to lint CSS and JSON too. Biome lints CSS, JSON, JSONC, and GraphQL with no extra plugins. ESLint requires
eslint-plugin-cssoreslint-plugin-json, which are community-maintained and often lag behind. - Dependency hygiene matters. A typical ESLint setup pulls in 50-200+ transitive dependencies. Biome is a single binary with zero JavaScript dependencies. Fewer dependencies means fewer supply chain risks and faster installs.
- You are tired of config conflicts. The ESLint + Prettier + TypeScript plugin dance is notoriously fragile. Biome eliminates entire categories of configuration issues because linting and formatting are unified.
Step-by-Step Migration: ESLint to Biome
Here is how to migrate an existing ESLint + Prettier setup to Biome:
Step 1: Install Biome
npm install --save-dev --save-exact @biomejs/biome
npx @biomejs/biome initThis creates a biome.json with recommended defaults. The --save-exact flag pins the version — Biome recommends this because minor versions can introduce new lint rules.
Step 2: Convert Your ESLint Config
Use the ESLint to Biome Converter to translate your existing rules. Paste your .eslintrc.json and get a biome.json with mapped rules, extracted formatter settings, and a list of unsupported rules that need manual review.
Alternatively, Biome has a built-in migration command:
npx @biomejs/biome migrate eslintThis reads your ESLint config and appends equivalent Biome rules to biome.json. It also runs migrate prettier automatically if it detects a Prettier config.
Step 3: Transfer Formatter Settings
If you were using Prettier, translate your settings to Biome's formatter section:
{
"semi": true,
"singleQuote": true,
"tabWidth": 2,
"trailingComma": "all",
"printWidth": 100,
"arrowParens": "always"
}{
"formatter": {
"indentStyle": "space",
"indentWidth": 2,
"lineWidth": 100
},
"javascript": {
"formatter": {
"semicolons": "always",
"quoteStyle": "single",
"trailingCommas": "all",
"arrowParentheses": "always"
}
}
}Step 4: Update Your Scripts
{
"scripts": {
"lint": "biome check .",
"lint:fix": "biome check --write .",
"format": "biome format --write ."
}
}biome check runs linting, formatting, and import sorting in a single pass. --write applies fixes in-place (equivalent to eslint --fix + prettier --write).
Step 5: Remove ESLint and Prettier
npm uninstall eslint prettier eslint-config-prettier \
eslint-plugin-react eslint-plugin-react-hooks \
@typescript-eslint/eslint-plugin @typescript-eslint/parser \
eslint-plugin-import eslint-plugin-jsx-a11y
rm .eslintrc.json .prettierrc .eslintignore .prettierignoreCheck your node_modules size before and after. It is common to see a 30-50 MB reduction from removing ESLint's dependency tree.
Step 6: Update CI and Editor
Replace ESLint and Prettier steps in CI with npx @biomejs/biome ci . (the ci command is like check but exits with a non-zero code on any issue). Install the Biome VS Code extension and remove the ESLint and Prettier extensions. Set Biome as the default formatter in .vscode/settings.json:
{
"editor.defaultFormatter": "biomejs.biome",
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"quickfix.biome": "explicit",
"source.organizeImports.biome": "explicit"
}
}Rule Coverage: What Biome Supports
Biome v2 ships with 280+ built-in lint rules organized into 8 categories: correctness, suspicious, style, complexity, a11y, security, performance, and nursery (experimental). It covers the majority of rules from these ESLint packages:
- ESLint core — ~60 of the most-used rules
- @typescript-eslint — 18+ rules including
no-explicit-any,no-non-null-assertion,consistent-type-imports - eslint-plugin-react / react-hooks — 10+ rules including
jsx-no-duplicate-props,rules-of-hooks - eslint-plugin-jsx-a11y — 26+ accessibility rules
- eslint-plugin-import — import sorting and
no-default-export
Notable gaps: Biome does not yet have equivalents for every rule in eslint-plugin-testing-library, eslint-plugin-security, or framework-specific plugins for Vue/Svelte/Angular.
Common Migration Pitfalls
- Formatting diff noise. Biome's formatter is Prettier-compatible but not identical. Expect minor whitespace differences. Run
biome format --write .once and commit the diff separately to keep your migration commit clean. - Stricter defaults. Biome's recommended rules are stricter than ESLint defaults. You may see new lint errors that ESLint never flagged. Review them — most are legitimate issues — or turn off specific rules you disagree with.
- Ignore patterns differ. Biome uses
biome.json'sfiles.ignorearray instead of.eslintignore/.prettierignore. Transfer your ignore patterns manually. - Inline disable comments. ESLint uses
// eslint-disable-next-line. Biome uses// biome-ignore lint/ruleName: reason. You will need to find and replace these across your codebase.
Example: Before and After
Here is a typical React + TypeScript ESLint config converted to Biome:
{
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"plugin:react/recommended",
"plugin:react-hooks/recommended",
"plugin:jsx-a11y/recommended",
"prettier"
],
"plugins": ["@typescript-eslint", "react", "import"],
"rules": {
"no-console": "warn",
"no-unused-vars": "off",
"@typescript-eslint/no-unused-vars": "error",
"@typescript-eslint/no-explicit-any": "warn",
"react/react-in-jsx-scope": "off",
"import/order": ["error", {
"groups": ["builtin", "external", "internal"]
}]
}
}{
"$schema": "https://biomejs.dev/schemas/2.0.0/schema.json",
"organizeImports": { "enabled": true },
"formatter": {
"indentStyle": "space",
"indentWidth": 2,
"lineWidth": 80
},
"linter": {
"enabled": true,
"rules": {
"recommended": true,
"correctness": {
"noUnusedVariables": "error"
},
"suspicious": {
"noExplicitAny": "warn",
"noConsole": "warn"
}
}
},
"javascript": {
"formatter": {
"semicolons": "always",
"quoteStyle": "double",
"trailingCommas": "all"
}
}
}The Biome config is shorter, needs no plugins, and covers linting, formatting, and import sorting in one file. The 8 npm packages from the ESLint setup are replaced by a single @biomejs/biome dependency.
Running Both Side by Side
If you cannot migrate all at once, Biome can run alongside ESLint. Use Biome for formatting only (replacing Prettier) while keeping ESLint for linting. This is a low-risk first step:
{
"scripts": {
"lint": "eslint .",
"format": "biome format --write .",
"check": "biome format . && eslint ."
}
}Once you are comfortable with Biome's formatting, enable Biome's linter for the rules it covers and gradually disable the equivalent ESLint rules. This phased approach reduces risk for larger teams.
The Bottom Line
ESLint is mature, flexible, and has unmatched plugin coverage. Biome is fast, simple, and eliminates entire categories of tooling complexity. For new projects and React/TypeScript codebases, Biome v2 is the better default in 2026. For projects that depend on framework-specific ESLint plugins or extensive custom rules, ESLint remains the safer choice — for now.
Ready to migrate? Use the ESLint to Biome Converter to translate your config automatically, and check the Biome Rule Mapping Reference to see exactly which ESLint rules have Biome equivalents.
Deploying your linted code to production?
DigitalOcean App Platform deploys Node.js, Next.js, and static sites with built-in CI/CD that runs your Biome checks automatically. Start with $200 free credit.