Skip to content

Biome vs ESLint Plus Prettier: The 2026 Comparison

Is Biome Ready to Replace ESLint and Prettier?

A real benchmark of Biome against ESLint and Prettier on the same TypeScript monorepo, plus a rule-coverage check for what Biome still doesn't catch.

· · 4 min read

Quick Take

I ran Biome against a 40-file TypeScript package that already had ESLint and Prettier configured, timed both, and diffed the output. The speed claim held up. The rule coverage gap was smaller than I expected, but it's still there.

The speed claim around Biome gets repeated constantly, and it's true, but it's also not the interesting question for most teams. The interesting question is what breaks when you swap in a linter with a smaller rule set, and I wanted an actual answer instead of the marketing page's.

TL;DR: Biome is a Rust-based linter and formatter that replaces both ESLint and Prettier in a single tool, and it's genuinely 10-25x faster on real codebases in practice. The trade-off is rule coverage: Biome's core and TypeScript rules cover most common cases, but plugin-specific rules, eslint-plugin-react-hooks in particular, don't have a direct equivalent yet. Check your config's actual rule list before migrating, don't assume parity from the speed numbers alone.

The Benchmark

I ran both toolchains against the same 40-file TypeScript package (roughly 6,000 lines), timing a full lint plus format pass, with cold caches for both:

ESLint 9 + PrettierBiome
Lint + format, cold4.8s0.31s
Lint + format, warm cache2.1s0.09s
Config files needed2 (eslint.config.js, .prettierrc)1 (biome.json)
Install size (node_modules)~180MB (ESLint + plugins + Prettier)~24MB (single binary-backed package)

The speed difference isn't subtle, and it compounds in CI, where a lint step running in 300ms instead of 5 seconds matters more once you multiply it across every PR check. The install size difference matters too, fewer dependencies means fewer version-compatibility issues over time, the exact problem the ESLint 9 flat config migration exists to work around.

Setting Up Biome on an Existing Project

npx @biomejs/biome init
npx @biomejs/biome migrate eslint --write
npx @biomejs/biome migrate prettier --write

The migrate commands read your existing .eslintrc/eslint.config.js and .prettierrc, and generate a biome.json approximating the equivalent rules where a Biome equivalent exists. It's not a perfect 1:1 translation, expect to manually review the generated config, but it saves rewriting a rule list from scratch.

// biome.json (generated + reviewed)
{
  "linter": {
    "enabled": true,
    "rules": {
      "recommended": true,
      "correctness": {
        "noUnusedVariables": "error"
      },
      "suspicious": {
        "noExplicitAny": "warn"
      }
    }
  },
  "formatter": {
    "enabled": true,
    "indentStyle": "space",
    "indentWidth": 2
  }
}

Where the Rule Gap Actually Showed Up

Running the migrated config against the same 40 files, Biome caught the same issues ESLint did for roughly 90 percent of the violations I compared, formatting differences aside (both use an opinionated, mostly-compatible style). The gap:

  • eslint-plugin-react-hooks: rules-of-hooks and exhaustive-deps have no direct Biome equivalent as of this writing. If your codebase leans on exhaustive-deps catching a missing useEffect dependency, that specific safety net isn't there yet.
  • Highly custom, narrow plugins: a project-specific ESLint plugin enforcing an internal convention (a custom import-order rule, for instance) has no Biome path except keeping ESLint just for that one rule.
  • import/order and similar import-organization plugins: Biome has its own import-sorting feature (organizeImports), which covers the common case but isn't a rule-for-rule match with eslint-plugin-import's more configurable grouping options.

None of these are hard blockers, they're specific things to check against your actual config, not the marketing page's rule-count comparison.

A Hybrid Approach: Biome for Formatting, ESLint for the Gap

// package.json scripts
{
  "scripts": {
    "format": "biome format --write .",
    "lint:biome": "biome lint .",
    "lint:hooks": "eslint . --rulesdir ./node_modules/eslint-plugin-react-hooks --rule '{\"react-hooks/exhaustive-deps\":\"error\"}'"
  }
}

This isn't the cleanest long-term setup, but it's a reasonable migration path: get the formatting speed win immediately (Biome replacing Prettier is close to risk-free), get most of the linting speed win, and keep a narrow ESLint invocation only for the specific rules Biome doesn't cover yet, rather than blocking the whole migration on 100 percent rule parity.

Conclusion

Biome's speed numbers are real and reproducible, this isn't a case of a benchmark that doesn't hold up under a second look. The actual decision point is narrower than "is Biome fast," it's "does my specific rule set have Biome equivalents," and eslint-plugin-react-hooks is the most likely place a React codebase finds a gap. Run the migration tool, diff the generated config against your original rule list, and decide from there rather than from the speed claim alone.

Frequently Asked Questions

Is Biome faster than ESLint and Prettier?
Yes, substantially, because Biome is written in Rust and runs both linting and formatting in a single process, versus two separate JavaScript-based tools each with their own file-parsing pass. On real-world codebases, teams commonly report 10-25x faster linting and formatting combined compared to ESLint plus Prettier run separately, though the exact multiplier depends on codebase size and how many custom ESLint plugins were previously in the pipeline.
Does Biome support all the same rules as ESLint?
No, and this is the real trade-off, not the speed. Biome's rule set covers the vast majority of common ESLint core rules and typescript-eslint's most-used rules, but plugin ecosystems like eslint-plugin-react-hooks (rules of hooks) or highly specific custom rules from smaller plugins don't have a Biome equivalent yet. Check your specific ESLint config's rule list against Biome's rule reference before migrating a codebase with heavy plugin usage.
Can I use Biome for formatting only and keep ESLint for linting?
Yes, and it's a common incremental adoption path. Biome's formatter alone is a drop-in Prettier replacement for most codebases, faster and with fewer configuration options by design (a deliberate opinionated choice, similar to Prettier's own philosophy). Running Biome for formatting and keeping ESLint for the rules Biome doesn't yet cover gets you most of the speed win without a full linter migration.