DEV Community

KahWee Teng
KahWee Teng

Posted on Originally published at kahwee.com

Your Linter Needs to Be as Fast as Your AI

I switched my own projects from ESLint to Biome because linting had become the slow part of an otherwise fast loop. Claude Code or Codex could hand me a complete patch, then ESLint made me wait to find out whether the patch was usable.

Biome made the save-and-check cycle feel immediate. I gave up a few type-aware rules I was barely reading anyway.

Where ESLint slowed me down

ESLint wasn't designed for a workflow where your AI commits 300 lines in one shot. It's a plugin framework, and every layer adds cost:

  • A parser (@typescript-eslint/parser, or Babel, or both)
  • Plugins that extend configs that extend other configs
  • Optional type-checking via tsconfig.json

That last one is the real killer. Type-aware rules like @typescript-eslint/no-floating-promises require ESLint to resolve your entire TypeScript type graph before running. On a medium-sized project, that's 15–30 seconds per run.

ESLint also runs on Node.js. Not a complaint — that's how it ships to everyone. But interpreted JavaScript is just slower than compiled code for CPU-bound parse work.

The result: most teams quietly disable type-aware rules because CI times balloon. Without them, ESLint catches style issues, not logic bugs. You're running a slow tool for modest returns.

What Biome changes

Biome is a linter and formatter written in Rust, with its own parser, and no dependency on the TypeScript compiler.

ESLint + Prettier Biome
Runtime Node.js (JavaScript) Native (Rust)
Parser External or separate Built-in
Formatter Prettier parses again Same AST as linter
Type-checking Optional, expensive None (syntax-only)
Config surface Plugins + extends chains Single biome.json

The double-parse problem alone matters at scale. ESLint parses your files, then Prettier parses them again for formatting. Biome parses once and runs both passes on the same AST.

According to Biome's own benchmarks, formatting runs ~25x faster than Prettier (multithreaded on modern hardware) and linting runs ~15x faster than ESLint on equivalent rule sets. Single-threaded, the numbers drop to around 7x and 4x respectively. Both figures come from Biome's benchmark suite, not independent testing — and the ESLint comparison deliberately excludes type-aware rules because Biome doesn't support them. Run the benchmark on your actual codebase before committing to the numbers.

Everything runs in parallel across files by default.

The setup I use

npm install --save-dev --save-exact @biomejs/biome
npx @biomejs/biome init
Enter fullscreen mode Exit fullscreen mode

init generates a biome.json. A working config for a TypeScript React project:

{
  "$schema": "https://biomejs.dev/schemas/1.9.0/schema.json",
  "organizeImports": {
    "enabled": true
  },
  "linter": {
    "enabled": true,
    "rules": {
      "recommended": true
    }
  },
  "formatter": {
    "enabled": true,
    "indentStyle": "space",
    "indentWidth": 2
  },
  "javascript": {
    "formatter": {
      "quoteStyle": "double",
      "trailingCommas": "es5"
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Add to package.json:

"scripts": {
  "lint": "biome lint ./src",
  "format": "biome format --write ./src",
  "check": "biome check --write ./src"
}
Enter fullscreen mode Exit fullscreen mode

biome check runs lint, format, and import sorting in one pass. That's the command you want on save and in CI.

For VS Code, install the Biome extension and set it as the default formatter:

{
  "[javascript]": { "editor.defaultFormatter": "biomejs.biome" },
  "[typescript]": { "editor.defaultFormatter": "biomejs.biome" },
  "[typescriptreact]": { "editor.defaultFormatter": "biomejs.biome" }
}
Enter fullscreen mode Exit fullscreen mode

Disable Prettier if it's installed — they'll conflict on save.

What I gave up

Biome's rule surface is smaller — around 250 rules vs ESLint's 1,000+. No @typescript-eslint/no-misused-promises. No eslint-plugin-react-hooks. No type-aware rules at all, because Biome doesn't run the TypeScript compiler. Custom rules written in JavaScript aren't possible; Biome's rules are compiled Rust, so you're limited to what the project ships.

Migrating also means a large formatting diff on day one. Biome's formatter matches Prettier's output in most cases, but not all. If your repo has clean formatting history, expect one noisy commit.

These are real limitations. Whether they matter depends on how much you rely on niche rules.

The linter has a smaller job now

ESLint's value was always in catching things humans missed — a convention violation, a misused promise, a forgotten dependency in a hook.

With AI generating the first draft, I can hand a lint error back to the agent that wrote the code. That makes quick feedback more useful to me than a large rule catalog that slows the loop down.

That changes what I need from a linter. It has to run on every save, catch obvious errors, and stay out of the way. Biome fits that job better in my projects than a large ESLint plugin stack.

Fast feedback is the feature

I switched from ESLint to Biome on my own projects. The speed difference was immediately obvious in the save-on-format loop. What I gave up: a handful of type-aware rules I was barely reading the output of anyway. What I gained: a linter I actually leave on.

Lint speed is part of the same AI coding loop in Claude Code: what I actually use.


Go deeper

How I think about code review when AI writes the first draft

Top comments (0)