---
title: "ESLint vs Biome"
slug: "eslint-vs-biome"
category: "comparisons"
tags: ["comparisons", "eslint", "biome", "linting", "formatting", "javascript", "tooling"]
status: "stable"
last_updated: 2026-05-29
summary: "Use Biome for new projects where the plugin ecosystem is not a constraint; use ESLint when you depend on plugins that Biome does not yet implement."
related: ["[[comparisons/biome-vs-eslint-prettier]]", "[[comparisons/swc-vs-babel]]", "[[comparisons/typescript-vs-flow]]", "[[comparisons/jest-vs-vitest]]", "[[coding/typescript]]", "[[tooling/github]]", "[[comparisons/vite-vs-webpack]]", "[[comparisons/yarn-vs-pnpm]]"]
---

## Overview

Use Biome on new projects. It combines a linter and formatter into one fast tool, eliminates Prettier as a separate dependency, and requires no plugin config for standard JavaScript and TypeScript. Use ESLint when your project requires plugins without Biome equivalents: `eslint-plugin-import`, `eslint-plugin-react-hooks`, accessibility rules from `eslint-plugin-jsx-a11y`, or custom corporate rule sets. This page is the linter-vs-linter cut; for the full lint-plus-format toolchain framing (Biome against ESLint and Prettier together), see [[comparisons/biome-vs-eslint-prettier]]. See [[comparisons/swc-vs-babel]] for the adjacent build-tool decision.

## When Biome wins

Biome is the right choice when the linting and formatting requirements are standard.

- Speed: Biome is written in Rust and runs lint and format in a single pass. On a 1000-file TypeScript project it typically completes in under 500 ms; ESLint with Prettier on the same project takes 5 to 15 seconds.
- Single tool: Biome replaces both ESLint and Prettier. One config file (`biome.json`), one dev dependency, one CI step.
- Zero config for TypeScript: `biome check .` works out of the box on TypeScript, JSX, and JSON without plugins or parser overrides.
- Consistent formatting: Biome's formatter is intentionally Prettier-compatible for most cases, so a migration from Prettier produces minimal diffs.
- No plugin hell: ESLint v8 to v9 flat config migration broke many plugins. Biome has no equivalent fragility.

```json
// biome.json
{
  "linter": { "enabled": true, "rules": { "recommended": true } },
  "formatter": { "enabled": true, "indentStyle": "space", "indentWidth": 2 },
  "javascript": { "formatter": { "quoteStyle": "double" } }
}
```

## When ESLint wins

ESLint is the right choice when plugin dependencies are real constraints.

- `eslint-plugin-react-hooks`: enforces the Rules of Hooks. Biome ships `useExhaustiveDependencies` and `useHookAtTopLevel` in its React domain, so the rules exist and are usable; they have known behavioral gaps versus ESLint's `react-hooks/exhaustive-deps`, so ESLint remains the stricter choice for hooks-heavy code.
- `eslint-plugin-import` and `eslint-plugin-boundaries`: graph-based import ordering and boundary enforcement. No Biome equivalent yet.
- `eslint-plugin-jsx-a11y`: accessibility linting for JSX. Critical for compliance-sensitive projects. Biome's a11y rules cover some cases but not all.
- Custom corporate rules: teams with internal `eslint-plugin-company-*` packages have no migration path to Biome.
- Framework-specific rule sets: `eslint-config-next`, `@angular-eslint`, and Nx lint presets all target ESLint.

Running both Biome (for formatting) and ESLint (for rules) is a valid hybrid. Disable Biome's linter and use it only for formatting, with ESLint handling rules.

## Trade-offs at a glance

| Dimension              | Biome                                    | ESLint (with Prettier)                       |
| ---------------------- | ---------------------------------------- | -------------------------------------------- |
| Speed                  | Very fast (Rust, single pass)            | Slower; scales poorly past 500 files         |
| Setup                  | One config file, zero plugins for basics | Multiple packages, possible parser conflicts |
| Formatting included    | Yes                                      | Only via Prettier integration                |
| TypeScript support     | Native                                   | Via `@typescript-eslint/parser`              |
| Plugin ecosystem       | Growing; 200+ rules built in             | Mature; thousands of plugins                 |
| React Hooks rules      | Present; gaps vs ESLint                  | Full via `eslint-plugin-react-hooks`         |
| Accessibility rules    | Partial                                  | Full via `eslint-plugin-jsx-a11y`            |
| Custom rules           | Plugins in development                   | Rich custom rule authoring                   |
| Config migration (v9)  | Not applicable                           | Flat config migration required for v9+       |
| Editor integration     | VS Code extension, CLI                   | All editors; mature support                  |

## Migration cost

ESLint plus Prettier to Biome is typically low-effort for standard configurations.

- `npx @biomejs/biome migrate eslint --write` reads `eslint.config.*` or `.eslintrc.*` and generates an initial `biome.json`. Handles common rule mappings automatically.
- Run `biome check --apply .` to auto-fix formatting and auto-fixable lint issues. Review the diff.
- Disable Prettier and ESLint in CI. Remove `eslint`, `prettier`, and related plugins from `package.json`.
- Expect to lose some rules that have no Biome equivalent. Audit the ESLint rule list against the Biome rule reference before committing.
- Effort: half a day for a 200-file project with a standard config; longer if custom plugins are in use.

## Recommendation

- New project with no special plugin requirements: Biome.
- New React project: Biome for formatting and most rules; add ESLint with `eslint-plugin-react-hooks` when you want the stricter hooks enforcement, since Biome's hooks rules have known gaps.
- Existing ESLint project, standard rules: migrate when you have CI time to spare. The speed win is real.
- Existing ESLint project with custom plugins or strict a11y requirements: stay on ESLint.
- Hybrid: valid. Use `biome format` only and ESLint for rules. Saves Prettier overhead without losing rule coverage.

## Related

- [[comparisons/biome-vs-eslint-prettier]]
- [[comparisons/swc-vs-babel]]
- [[comparisons/typescript-vs-flow]]
- [[comparisons/jest-vs-vitest]]
- [[coding/typescript]]
- [[tooling/github]]
- [[comparisons/vite-vs-webpack]]
- [[comparisons/yarn-vs-pnpm]]
