Biome vs ESLint + Prettier: One Rust Toolchain to Replace Two

Photo by Nemuel Sereti on Pexels
Yes, significantly. Because Biome is compiled Rust rather than Node-based JavaScript, its own benchmark reports formatting around 35 times faster than Prettier on 171,127 lines across 2,104 files. In practice a full format-and-lint pass on a large project finishes in well under a second.
For new projects or codebases whose rules map cleanly onto Biome's set, yes — it formats and lints from one binary and one biome.json. For mature projects that rely on niche ESLint plugins, custom rules, or deep type-aware linting, ESLint plus Prettier may still be the safer choice.
Install @biomejs/biome, run biome init, then biome migrate eslint --write and biome migrate prettier --write. These commands read your existing configs and port the settings into biome.json. Finally run biome check --write to format, lint, and apply safe fixes in one pass.
Biome claims about 97 percent compatibility with Prettier across JavaScript, TypeScript, JSX, JSON, CSS, and GraphQL, so most files come out byte-identical. The remaining differences are documented, and Biome defaults to tabs where Prettier defaults to spaces, so review your first diff.
Its plugin ecosystem is much smaller and still maturing than ESLint's thousands of plugins, framework support for Vue, Svelte, and Astro is experimental, and its type-aware rules infer types without the TypeScript compiler, catching roughly 75 percent of the cases typescript-eslint would. Some languages like SCSS, YAML, and Markdown are still in progress.

Photo by Nemuel Sereti on Pexels
Key Takeaway
Biome is a single Rust-based tool that formats and lints JavaScript and TypeScript, aiming to replace the ESLint plus Prettier pair. It is roughly 35 times faster than Prettier, offers 97 percent Prettier compatibility, and uses one biome.json file, but its plugin ecosystem and framework coverage remain narrower than ESLint's mature stack.
For years the default JavaScript setup meant wiring two tools that overlap and occasionally fight: Prettier owns formatting, ESLint owns code quality, and you spend an afternoon with eslint-config-prettier making sure they stop arguing over the same semicolons. Both run on Node, so on a large repo they are also slow enough that people quietly disable them in their editor.
Biome, which grew out of the earlier Rome project, takes the opposite bet. It is one binary, written in Rust, that formats and lints from a single configuration file. I moved a mid-sized TypeScript codebase onto it and want to give you the version I wish I had read first: what genuinely improves, what is a real trade-off, and where ESLint still wins.
The most immediate change is not speed, it is the reduction in moving parts. A typical ESLint plus Prettier setup carries a .eslintrc, a .prettierrc, two ignore files, and a pile of plugin and config packages just to make them coexist. Biome collapses that into a single biome.json and a single dependency. There is no bridge package whose only job is to stop your formatter and linter from disagreeing, because the same engine does both.
Because Biome is compiled Rust rather than interpreted JavaScript, it is in a different performance class. The project's own benchmark reports Biome formatting around 35 times faster than Prettier on a corpus of 171,127 lines across 2,104 files. In day-to-day use the effect is that a full format-and-lint pass on a large project finishes in well under a second, which is what makes running it on every save and in a pre-commit hook painless rather than annoying.
The single most useful command is check, which formats, lints, and organizes imports in one pass. Run biome check --write on a directory and it applies every safe fix at once, so you replace both prettier --write and eslint --fix with one invocation.
Biome reads a single biome.json (or biome.jsonc) from the project root and walks up parent directories to find it. A pragmatic starting config turns on the formatter, the recommended lint rules, and Git-aware ignore handling. Note the schema URL is pinned to a version so your editor gives accurate autocomplete:
{
"$schema": "https://biomejs.dev/schemas/2.5.0/schema.json",
"vcs": {
"enabled": true,
"clientKind": "git",
"useIgnoreFile": true
},
"formatter": {
"enabled": true,
"indentStyle": "space",
"indentWidth": 2,
"lineWidth": 100
},
"linter": {
"enabled": true,
"rules": {
"recommended": true
}
},
"javascript": {
"formatter": {
"quoteStyle": "single",
"semicolons": "always"
}
}
}You do not have to translate your rules by hand. Biome ships migrate subcommands that read your existing ESLint and Prettier configuration and port the settings into biome.json for you. The workflow is install, init, migrate, then check:
# Install the single binary, pinned to an exact version
npm install --save-dev --save-exact @biomejs/biome
# Generate a starter biome.json
npx @biomejs/biome init
# Port your existing ESLint and Prettier settings into biome.json
npx @biomejs/biome migrate eslint --write
npx @biomejs/biome migrate prettier --write
# Format, lint, and apply safe fixes in one pass
npx @biomejs/biome check --write ./srcThe formatter targets Prettier output deliberately, claiming 97 percent compatibility across JavaScript, TypeScript, JSX, JSON, CSS, and GraphQL, so most files come out byte-identical. The remaining few percent are documented differences, and Biome also defaults to tabs where Prettier defaults to spaces, so review the first diff rather than assuming a perfect match.
Biome is not a drop-in for every ESLint setup, and pretending otherwise wastes your time. The gaps cluster in three areas: the plugin ecosystem, framework file coverage, and type-aware rules. If your project leans on a niche ESLint plugin or a hand-written custom rule, check for a Biome equivalent before committing to the switch.
ESLint has hundreds of community plugins and years of custom rules built on its full AST access. Biome's plugin system is deliberately narrower and still maturing, and its type-aware rules infer types without the TypeScript compiler, so a rule like noFloatingPromises catches roughly 75 percent of the cases typescript-eslint would. Verify the specific rules you depend on are covered.
| Concern | Biome | ESLint + Prettier |
|---|---|---|
| Tools to install | One binary | Two tools plus bridge and plugin packages |
| Runtime | Rust, compiled native | JavaScript on Node |
| Formatting speed | Around 35 times faster than Prettier | Prettier baseline |
| Configuration | Single biome.json | Separate ESLint and Prettier files plus ignores |
| Lint rules built in | Over 500 rules, no plugins needed | Core rules plus plugins for the rest |
| Plugin ecosystem | Small and still maturing | Large and battle-tested |
| Type-aware rules | Partial, inferred without tsc | Full via typescript-eslint |
My verdict after the migration: for a new project, or an existing one whose lint rules map cleanly onto Biome's set, the switch is an easy win — you trade a pile of dependencies for one fast binary and lose almost nothing. For a mature codebase that leans on specialized ESLint plugins or deep type-aware rules, stay on ESLint plus Prettier a while longer, or run Biome only as the formatter and keep ESLint for the rules it uniquely provides.