· biome / eslint / prettier

Biome 2 Review — Ready to Replace Prettier and ESLint?

Biome v2 fills the biggest gaps from v1: multi-file analysis, type-aware linting without tsc, and custom rules via GritQL. Is it enough for your stack?

By · Updated June 1, 2026

1,709 words · 9 min read

For a pure TypeScript or JavaScript project — a Next.js app, a Node API, a component library — Biome v2 is ready to replace Prettier and ESLint today. The v2 upgrade fixed the hard blockers from v1: it does multi-file analysis, it catches type errors without running tsc, and it supports custom rules. The speed advantage is structural and not going away.

If your stack runs Vue, Svelte, or Astro in production, or you have years of ESLint plugins doing complex semantic analysis, wait another two to four quarters. The capability is coming. It’s not stable for those cases yet.

Who this is for

TypeScript teams on a monorepo — five to fifty engineers — weighing whether to replace Prettier and ESLint with a single tool. If you’re a solo developer on one small package, skip to the verdict. If your team runs Vue or Svelte as the primary framework, start at caveats.

What we tested

Biome v2.4.16, released 2026-05-27 — the latest stable release. Benchmarks come from Biome’s published figures and independently verified third-party measurements, with methodology flagged per claim. Where a number is self-reported, we say so.

What is new in Biome v2

The jump from v1 to v2 is not a polish release. These are the features that change the migration calculus.

Type-aware linting without the TypeScript compiler

In v1, rules that required type information needed tsc to run — slow, complex to configure, not worth it for pre-commit hooks. Biome v2 implements its own type inference layer. It’s not a full TypeScript compiler, but it catches noFloatingPromises (unhandled async calls), noMisusedPromises, and other async-footgun rules. Biome’s own published data shows noFloatingPromises catching ~75% of cases that @typescript-eslint/no-floating-promises would flag.

That’s not full typescript-eslint parity. But the rules Biome implements cover the async footguns and null-path bugs that actually bite people in production — without the 45-second type-check overhead. For most codebases, this is enough.

Multi-file analysis

Two new rules: noImportCycles and noPrivateImports. Circular dependency detection now happens at lint time rather than at runtime or during a 2am incident. These rules were impossible in Biome v1’s single-file model. For monorepos with shared packages, noImportCycles alone is worth the migration.

GritQL plugin system

Custom lint rules are now possible. GritQL is a pattern-matching language — you write something like js`console.log($msg)` to match any console.log call and flag it. More complex patterns handle things like restricting imports from specific paths or requiring certain argument shapes.

It is not ESLint’s full JavaScript AST plugin system. Rules that need scope analysis, type flow, or cross-file state can’t be expressed in GritQL today. But the majority of internal ESLint rules I’ve seen at teams are pattern-matching rules — banning deprecated APIs, enforcing import shapes, flagging console calls. GritQL handles those.

Domains

Biome reads your package.json and auto-enables relevant rule sets. React project? React rules on. Jest in devDependencies? Jest rules activate. Next.js in dependencies? Next.js-specific rules fire. You don’t configure this — it’s detected from what you already have installed.

Revamped import organizer

The v1 import sorter worked. The v2 version handles merging duplicate imports, correctly splits type/value/side-effect buckets, and supports custom group ordering. This removes the last reason to keep prettier-plugin-organize-imports or eslint-plugin-import’s sort rules in your stack.

Monorepo support

"root": false in a nested biome.json lets individual packages extend the root config without resetting it. This was a hard blocker in v1 — the config inheritance was too aggressive and forced teams to duplicate settings. A monorepo with ten packages can now have a single root config plus per-package overrides without fighting the tool.

Embedded language support (v2.4)

Biome v2.4 added correct formatting and linting for CSS and GraphQL embedded inside styled-components and Emotion blocks. This was a meaningful gap for React shops — styled-components is the dominant CSS-in-JS approach, and having Biome silently skip those blocks caused format drift between the formatter and the code.

The same release added 15 HTML accessibility rules (for HTML formatting, which is experimental and off by default).

Vue, Svelte, Astro (v2.3, experimental)

These landed in v2.3. The Biome team flags edge cases in templating syntax. Coverage is not at parity with the JS/TS surface. Treat this as beta — it’s useful for teams who want to start testing it, but not yet production-stable.

Performance

The numbers Biome publishes are real — for Biome’s benchmark conditions:

ScenarioESLint / PrettierBiomeSource
Format 171,127 lines / 2,104 files (i7 1270P)Prettier baseline35× fasterBiome (self-reported)
Pre-commit hook, large TS monorepo27.2 s1.8 s (15×)Third-party case study

The 35× is Biome’s own benchmark — treat it as an upper bound under near-ideal conditions. The 15× pre-commit number (92.6% reduction) comes from an independently verifiable real-world production migration, not a synthetic fixture.

On a typical mid-size TypeScript monorepo, expect 8–15× faster in practice. The biggest gains are in CI and pre-commit hooks, where cold-start overhead (Node.js startup, ESLint plugin resolution, type-checker invocation) was the dominant cost. On a repo where lint finishes in under two seconds today, the improvement is real but you won’t feel it.

The structural reason the gap exists: single Rust binary, full CPU parallelism (ESLint is single-threaded by default), no Node.js startup overhead, no plugin resolution chain. That gap doesn’t shrink as Biome adds more rules.

Rule coverage and gaps

CategoryBiome v2.4.16
Core ESLint recommended~94% of commonly-used rules
typescript-eslint type-awarePartial — key async rules (noFloatingPromises, noMisusedPromises) covered; scope/type-flow rules not
React / JSX~90%+
CSSFormatting + basic linting
Vue / Svelte / AstroExperimental (v2.3+)
HTML formattingExperimental, off by default
MarkdownOn 2026 roadmap, not shipped
Shareable config ecosystemThin vs. ESLint’s catalog

Two gaps that will actually affect you:

react-hooks/exhaustive-deps: Biome ships a basic version. The eslint-plugin-react-hooks rule handles complex dependency expression analysis that Biome’s implementation misses in some cases. If you enforce strict hooks discipline on a large React codebase, run both versions and compare the output before removing ESLint.

Custom rules via GritQL: Pattern-matching handles most convention enforcement. It does not handle rules that need full semantic analysis — scope chain, type flow, cross-file state. If you maintain internal ESLint plugins for those cases, keep ESLint for that subset or accept the coverage reduction.

For a detailed rule-by-rule breakdown, see our Biome vs ESLint comparison.

Migration

The official migration commands do the bulk of the work:

npm install --save-dev --save-exact @biomejs/biome
npx @biomejs/biome init

# Import existing configs:
npx @biomejs/biome migrate eslint --write
npx @biomejs/biome migrate prettier --write

# CI check:
npx @biomejs/biome ci .

On a mid-size monorepo, budget 1–4 hours total:

  • 30–60 min — running the commands, reading the migration report (the migrate commands output what they couldn’t translate; read it before assuming success)
  • 30–90 min — resolving untranslated rules (YAML configs are unsupported; JS config files need Node.js to run, require manual conversion to JSON)
  • 30–60 min — reviewing the formatting diff (Biome and Prettier are not 100% behaviorally identical — the first format pass touches many files; land this as a separate commit)
  • 15–30 min — enabling VCS integration manually (Biome doesn’t auto-detect .gitignore; add vcs.enabled = true and vcs.useIgnoreFile = true to biome.json)

The formatting diff commit is noise. Land it separately with a clear message so reviewers can skip it when reviewing the actual logic changes.

For a complete walkthrough including editor setup, CI configuration, and .gitignore handling, see How to migrate from ESLint and Prettier to Biome.

Editor support

The VS Code extension V3 (April 2025) covers the main cases: multi-root workspace support, single-file mode for files outside a biome.json project, auto-reload on config change, and format-on-save for unsaved buffers. The built-in biome binary downloader was removed — install @biomejs/biome locally per project. That’s the correct practice anyway; it pins the version to the repo rather than to whatever the extension downloaded.

JetBrains support exists as a community plugin. It works, but the integration is noticeably less polished than the VS Code extension. If your team primarily uses IntelliJ or WebStorm and depends on tight editor formatting-on-save behavior, budget some friction during rollout.

Verdict

Switch today if:

  • Your stack is pure TypeScript or JavaScript (Next.js, React, Node, Remix)
  • CI lint and format runs take more than 30 seconds and you want that fixed this week
  • You can accept partial typescript-eslint type-aware coverage — async footguns like noFloatingPromises and noMisusedPromises are covered, but scope-chain and type-flow rules are not
  • You don’t maintain internal ESLint plugins requiring semantic analysis

Wait 6–12 months if:

  • Your primary framework is Vue, Svelte, or Astro (experimental support is not production-stable)
  • You rely heavily on exhaustive-deps edge cases
  • You maintain internal ESLint plugins that need scope-chain or type-flow analysis

Skip for now if:

  • You need Markdown formatting (on the 2026 roadmap, not yet shipped)
  • You run more than ten custom ESLint plugins, several of which need semantic analysis beyond pattern matching

Caveats

The self-reported 35× benchmark is an upper bound. Biome’s methodology is transparent, but the conditions favor parallelism. Real-world speedup depends on your ESLint plugin weight, file count, and hardware. The 8–15× estimate for typical projects comes from actual reported migrations, not synthetic fixtures.

GritQL’s limits for non-trivial custom rules were not exhaustively tested here. If you maintain complex internal lint plugins, run a pilot on one package before migrating the full monorepo.

Vue/Svelte/Astro: “experimental” is the Biome team’s own label. If those are your primary frameworks, this review is not a complete picture of your migration risk.

Biome is free and open-source. No affiliate program exists — no affiliate relationship here.

References