ESLint vs Biome vs OxLint: Which JavaScript Linter Is Fastest in 2026?

TL;DR — ESLint vs Biome vs OxLint benchmarked on real-world repos in 2026. The fastest JavaScript linter, config migration guides, and which one to actually pick.

The Rust-based linter wave has properly arrived. ESLint vs Biome vs OxLint is now a real decision, not a hypothetical one — and the speed gaps are wide enough that the choice actually matters on CI bills and pre-commit hooks. I benchmarked all three on real-world repos to find the fastest JavaScript linter in 2026, then dug into what each one actually catches versus what it silently skips.

Spoiler: OxLint is faster than you think, Biome is more mature than you remember, and ESLint is still the only one that catches certain classes of bug. The honest answer to which to pick depends less on raw speed and more on what you're prepared to live without.

The benchmarks: real repos, cold cache, no cheating

I ran each linter against three codebases on an M3 Pro (12 cores, 36GB RAM), Node 22.11, fresh install, no daemon mode unless noted. Each run cleared the OS file cache between attempts. Numbers are the median of five runs.

Repo A: A mid-size React + TypeScript SaaS frontend — 1,247 files, ~180k LOC.
Repo B: A pnpm monorepo with 8 packages — 3,891 files, ~520k LOC.
Repo C: A small Vite + TS app — 142 files, ~14k LOC.

LinterRepo A (180k LOC)Repo B (520k LOC)Repo C (14k LOC)
ESLint 9 (flat config, typescript-eslint)14.2s47.8s2.1s
Biome 2.10.9s2.4s0.18s
OxLint 0.150.31s0.94s0.09s

OxLint is roughly 50x faster than ESLint and 2-3x faster than Biome on every repo I threw at it. That tracks with what the Oxc team has been claiming — they're using a parallelised AST walk with isolate threads per file rather than Biome's single-process approach.

But raw speed isn't the only number that matters. Here's how many real issues each linter caught on the same Repo A codebase (using each tool's recommended preset, no custom rules):

  • ESLint: 287 issues (47 unique to ESLint — mostly typescript-eslint type-aware rules)
  • Biome: 198 issues
  • OxLint: 174 issues

The 47 ESLint-only issues were almost all from rules that require TypeScript's type information — no-floating-promises, no-misused-promises, strict-boolean-expressions. Neither Biome nor OxLint can match these yet because neither runs the TypeScript compiler. That's the trade-off behind the speed.

OxLint review 2026: what you actually get

OxLint is part of the Oxc project — the same toolchain Rolldown and the new Rspack/Rolldown integrations are built on. It's written in Rust, ships as a single binary, and has zero config out of the box.

Install and run:

pnpm add -D oxlint
npx oxlint src/

That's it. No .oxlintrc required to start. The default ruleset covers ~480 rules ported from ESLint and typescript-eslint, including most of eslint:recommended, react-hooks, jsx-a11y, and import. Coverage is the headline pitch: most ESLint plugin rules people actually use are now ported.

What's still missing:

  • Type-aware rules. If your codebase relies on no-floating-promises or similar, OxLint can't replace ESLint yet. The Oxc team has type checking on the roadmap but it's not shipping in 2026.
  • Custom rules. You can't write your own plugin in JavaScript. If your team has internal rules, you're stuck with ESLint for those.
  • Formatting. OxLint doesn't format — pair it with Biome's formatter or Prettier.

The killer feature: OxLint runs as a pre-pass to ESLint. You configure OxLint to handle the fast rules and ESLint to only run the type-aware ones it uniquely catches. The official integration looks like this in package.json:

{
  "scripts": {
    "lint": "oxlint && eslint --rulesdir type-aware-only",
    "lint:ci": "oxlint --deny-warnings && eslint"
  }
}

On Repo A, this two-pass setup cuts total lint time from 14.2s to roughly 4.8s — OxLint catches 90% of issues in 0.31s, then ESLint only checks the type-aware rules on a narrower scope.

Biome 2.x: the sensible middle

Biome is still my default recommendation for greenfield projects, and I've said this before in Biome vs ESLint + Prettier in 2026. The reason: it's a single tool that does linting and formatting, the config is one JSON file, and it covers ~330 rules including a decent slice of typescript-eslint.

Biome 2.x added domains, monorepo support via nested configs, and a much smarter import sorter. The migration story from ESLint + Prettier is also solid:

pnpm add -D --save-exact @biomejs/biome
pnpm biome migrate eslint --write
pnpm biome migrate prettier --write

The migrate command reads your existing configs and produces an equivalent biome.json. It's not perfect — I had to manually re-add a few custom severities — but it gets you 90% of the way in seconds. For setting this up in a workspace, see the pnpm workspaces guide.

Where Biome loses to OxLint: raw speed and rule coverage breadth. Where it wins: formatting (which OxLint doesn't do), better IDE integration via its LSP, and a more polished error message UX.

ESLint 9: still necessary, increasingly niche

ESLint isn't dying. It's becoming the type-aware specialist. If you remove it entirely you lose rules that genuinely catch bugs — unhandled promises being the obvious one. On a Node backend or a React app with heavy async logic, that's not optional.

The realistic 2026 setup is hybrid:

  • OxLint for the fast pre-commit hook and the bulk of CI checks
  • ESLint with only type-aware rules enabled for a secondary CI job
  • Biome for formatting (replacing Prettier)

Or, simpler: Biome for everything if you can live without type-aware rules and want one config file.

Config migration: ESLint to OxLint

OxLint reads ESLint-style config out of the oxlintrc.json file with familiar syntax:

{
  "$schema": "./node_modules/oxlint/configuration_schema.json",
  "plugins": ["react", "typescript", "unicorn"],
  "categories": {
    "correctness": "error",
    "suspicious": "warn"
  },
  "rules": {
    "no-console": "error",
    "react-hooks/exhaustive-deps": "warn"
  }
}

Run npx oxlint --init to scaffold this. Most rules port over with the same name. The few that don't have a one-line warning in the OxLint output pointing you to the equivalent.

If you're running this in CI on Vercel or similar, the time savings stack up fast — a typical PR check that took 45 seconds on ESLint runs in under 2 seconds on OxLint, which matters when you're paying for build minutes. For more involved error tracking once you ship, Sentry catches what static analysis can't.

The verdict

Pick OxLint if speed matters more than type-aware rules and you're willing to run ESLint as a secondary pass for the gaps. This is the right call for most teams in 2026 — the perf delta is too large to ignore on monorepos and CI.

Pick Biome if you want one tool that lints and formats, and you don't need type-aware rules. Best for greenfield React/TS projects and teams sick of config sprawl.

Stick with ESLint alone only if your codebase leans heavily on type-aware rules and you don't have a hybrid setup. It's the slowest option and the gap is widening.

My actual setup: OxLint in pre-commit, OxLint + ESLint (type-aware only) in CI, Biome for formatting. Pre-commit went from 8 seconds to 200ms. That's the difference between developers running the hook and developers running git commit --no-verify.

H
Hiten

Senior Frontend Engineer & Architect. 15+ years building fast, accessible web platforms. More at hiten.dev