Skip to main content

Biome vs ESLint + Prettier: The Linter Wars 2026

·PkgPulse Team

Before Biome, linting and formatting a typical JavaScript project required 127 npm packages, 3 config files, and a lint-staged hook that took seconds to run. Biome replaces all of that with a single binary that runs in 50ms. The question isn't whether Biome is faster — it's 10-25x faster. The question is whether "10-25x faster" matters enough to migrate from the ESLint ecosystem you already know.

TL;DR

Biome is the right choice for new projects, or for projects where lint/format speed is noticeably impacting developer experience. ESLint + Prettier is still the right choice for projects that rely on framework-specific ESLint plugins (Next.js, React, TypeScript strict rules) that Biome doesn't yet fully replicate. Biome v2.x has closed the gap significantly — but not all the way.

Key Takeaways

  • Biome: formats 1K files in 50ms vs. Prettier's 1-2s; lints 10K files in 0.8s vs. ESLint's 45s
  • biome: ~500K weekly npm downloads, 20K+ GitHub stars — fast growing
  • eslint: 68M+ weekly downloads — still dominant by 100x
  • Biome ships as a single binary with zero npm dependencies (127 packages → 1)
  • Biome v2.x (2026) has 423+ lint rules and type-aware linting support
  • Biome's formatter is 96%+ compatible with Prettier for most codebases
  • ESLint's plugin ecosystem (typescript-eslint, eslint-plugin-react, etc.) is irreplaceable for now

What Biome Is

Biome is a Rust-powered toolchain for JavaScript/TypeScript that replaces multiple tools at once:

  • Formatter: Prettier replacement
  • Linter: ESLint replacement
  • Import organizer: perfectionist/eslint-plugin-import replacement
  • (Planned): Bundler, test runner, type checker

It was forked from Rome (abandoned) and has been maintained by an active community since 2023. The current stable version is v2.x (2026).

Installation

# ESLint + Prettier (current setup)
npm install -D eslint @eslint/js eslint-config-prettier prettier typescript-eslint
# + plugins: eslint-plugin-react, eslint-plugin-jsx-a11y, etc.
# = 127 packages in node_modules

# Biome (alternative)
npm install -D --save-exact @biomejs/biome
# = 1 package

Configuration Comparison

Biome Config

// biome.json
{
  "$schema": "https://biomejs.dev/schemas/2.0.0/schema.json",
  "vcs": {
    "enabled": true,
    "clientKind": "git",
    "useIgnoreFile": true
  },
  "organizeImports": {
    "enabled": true
  },
  "linter": {
    "enabled": true,
    "rules": {
      "recommended": true,
      "correctness": {
        "noUnusedVariables": "error",
        "noUnusedImports": "error"
      },
      "suspicious": {
        "noExplicitAny": "warn"
      },
      "style": {
        "useConst": "error",
        "noVar": "error"
      }
    }
  },
  "formatter": {
    "enabled": true,
    "indentStyle": "space",
    "indentWidth": 2,
    "lineWidth": 100
  },
  "javascript": {
    "formatter": {
      "quoteStyle": "single",
      "trailingCommas": "es5",
      "semicolons": "always"
    }
  }
}

ESLint + Prettier Config (Flat Config)

// eslint.config.js
import js from '@eslint/js';
import ts from 'typescript-eslint';
import react from 'eslint-plugin-react';
import reactHooks from 'eslint-plugin-react-hooks';
import a11y from 'eslint-plugin-jsx-a11y';

export default ts.config(
  js.configs.recommended,
  ...ts.configs.strictTypeChecked,
  {
    plugins: {
      react,
      'react-hooks': reactHooks,
      'jsx-a11y': a11y,
    },
    rules: {
      'react-hooks/rules-of-hooks': 'error',
      'react-hooks/exhaustive-deps': 'warn',
      'jsx-a11y/anchor-is-valid': 'error',
      // ... 50 more rules
    },
  }
);

// .prettierrc
// { "semi": true, "singleQuote": true, "tabWidth": 2 }

Biome: 1 file. ESLint + Prettier: 2-3 files, 127 packages.

Speed Benchmarks

Linting (10,000 TypeScript files)

ToolTime
Biome0.8s
ESLint (no type-checking)45s
ESLint (with typescript-eslint type-aware)120s+

Formatting (10,000 files)

ToolTime
Biome0.3s
Prettier12.1s

Pre-commit Hook Impact (typical project, 50 staged files)

ToolTime
Biome~200ms
ESLint + Prettier3-8s

The pre-commit time difference is the one developers feel most directly. Waiting 5+ seconds for every commit is a real friction point.

Rule Coverage Comparison

What Biome Has (423+ rules in v2.x)

  • Core correctness rules (unused vars, typeof, no-debugger, etc.)
  • TypeScript-aware rules (no-any, consistent-type-imports)
  • Style rules (const, no-var, arrow functions)
  • Import organization
  • Security rules (no-dangerouslySetInnerHTML, eval)

What ESLint Has That Biome Lacks

CategoryESLint PluginsBiome Status
React Hooks ruleseslint-plugin-react-hooksPartial (improving)
Accessibilityeslint-plugin-jsx-a11yNot yet
Next.js specificeslint-config-nextNot yet
Import sortingeslint-plugin-importYes (built-in)
Perfectionist sortingeslint-plugin-perfectionistPartial
Tailwind class sortingeslint-plugin-tailwindcssNot yet
Storybookeslint-plugin-storybookNo

The accessibility and React Hooks coverage gap is the most significant blocker for large React applications.

Prettier Compatibility

Biome's formatter achieves 96%+ compatibility with Prettier's output for most codebases. The remaining 4% is mostly edge cases with complex template literals and certain JSX patterns.

# Check Prettier compatibility for your codebase
npx @biomejs/biome format --write src/
# Then: git diff --stat to see what changed

Migration Strategy

New Projects: Start with Biome

npx @biomejs/biome init
# Creates biome.json with recommended settings

# Replace package.json scripts
# Before:
"lint": "eslint . --ext .ts,.tsx",
"format": "prettier --write .",
"lint:fix": "eslint . --fix && prettier --write .",

# After:
"lint": "biome lint ./src",
"format": "biome format ./src --write",
"check": "biome check ./src",  # lint + format together

Existing Projects: Gradual Migration

Option 1: Run Biome alongside ESLint (transitional)

npm install -D @biomejs/biome

# biome.json — disable rules covered by ESLint plugins you're keeping
{
  "linter": {
    "rules": {
      "recommended": false,  // Start with nothing
      "correctness": { "noUnusedVariables": "error" }
    }
  },
  "formatter": { "enabled": true }  // Replace Prettier immediately
}

Option 2: Biome for formatting, ESLint for linting (common hybrid)

Many teams replace Prettier with Biome's formatter (easy, high benefit) while keeping ESLint for linting (retains plugin ecosystem):

# Remove prettier and eslint-config-prettier
npm uninstall prettier eslint-config-prettier

# Add biome for formatting only
npm install -D @biomejs/biome
// biome.json
{
  "linter": { "enabled": false },
  "formatter": { "enabled": true }
}
// eslint.config.js — no more prettier integration needed

This hybrid reduces complexity while keeping ESLint's plugin ecosystem.

VS Code Integration

Both have strong editor support:

// .vscode/settings.json — Biome
{
  "editor.defaultFormatter": "biomejs.biome",
  "editor.formatOnSave": true,
  "[javascript]": { "editor.defaultFormatter": "biomejs.biome" },
  "[typescript]": { "editor.defaultFormatter": "biomejs.biome" }
}

// .vscode/settings.json — ESLint + Prettier
{
  "editor.defaultFormatter": "esbenp.prettier-vscode",
  "editor.formatOnSave": true,
  "eslint.validate": ["javascript", "typescript", "javascriptreact", "typescriptreact"]
}

CI/CD Performance Impact

For a monorepo with 50K files:

Tool StackCI lint + format time
ESLint + Prettier8-15 minutes
Biome30-60 seconds

This is where the speed advantage translates directly to developer velocity and CI costs.

When to Choose Biome

Choose Biome if:

  • Starting a new project
  • Your pre-commit hooks are noticeably slow (>3 seconds)
  • CI lint time is a bottleneck
  • You're in a monorepo where ESLint runs multiple times
  • Your project doesn't rely on jsx-a11y or complex React plugin rules
  • You want fewer dependencies and simpler config

Keep ESLint + Prettier if:

  • You rely on eslint-plugin-jsx-a11y for accessibility enforcement
  • eslint-plugin-react-hooks rules are critical to your codebase
  • eslint-config-next catches Next.js-specific errors
  • Your team has complex custom ESLint rules
  • Migrating would disrupt a large existing codebase

The 2026 Landscape

The trend is clear: Biome's adoption is accelerating, and its rule coverage is rapidly closing the gap with ESLint plugins. By 2027, expect Biome to have React Hooks and accessibility rules, at which point the migration case becomes overwhelming.

For now, the pragmatic choice for most JavaScript/TypeScript projects is to use Biome's formatter (immediate win, easy migration) and evaluate switching linting based on whether you need specific ESLint plugins.

Compare biome vs eslint download trends on PkgPulse.

Comments

Stay Updated

Get the latest package insights, npm trends, and tooling tips delivered to your inbox.