Code Formatters Compared: Prettier, Black, gofmt, rustfmt, and More
Code formatting debates are a spectacular waste of engineering time. Tabs vs. spaces, brace placement, line length, trailing commas — teams can spend hours arguing about preferences that have zero impact on code quality or performance. The only winning move is to stop playing: adopt an opinionated formatter, configure it once, and never discuss formatting again.
The best code formatters are opinionated by design. They offer minimal configuration, enforcing a consistent style that removes formatting from code reviews and merge conflicts. The result is that developers focus on logic, not layout.
Here is a practical guide to code formatters across major languages, including the newer tools that are challenging the incumbents.
The Philosophy of Code Formatting
Code formatters sit on a spectrum from highly configurable to completely opinionated:
Highly configurable (many options): ESLint --fix, clang-format
These tools let you configure hundreds of formatting options. The flexibility is the problem — you still have to debate and decide every option.
Moderately configurable (some options): Prettier, rustfmt
These tools have sensible defaults and a handful of options for the most contentious settings (line length, tab width). Most teams use defaults.
Completely opinionated (zero or near-zero options): gofmt, Black
These tools have one style. You cannot change it. This is intentional and liberating.
JavaScript/TypeScript
Prettier
Prettier is the dominant code formatter for JavaScript, TypeScript, HTML, CSS, JSON, Markdown, YAML, and GraphQL. It reformats your code from an AST (abstract syntax tree) — it does not modify your code, it prints it from scratch in a consistent style.
Strengths
- Multi-language: Handles JS, TS, HTML, CSS, JSON, Markdown, and more — one tool for your entire frontend
- AST-based: Reformats from the syntax tree, ensuring consistent output regardless of input formatting
- Minimal configuration: Only a handful of options (printWidth, tabWidth, singleQuote, trailingComma, semi, bracketSpacing)
- Editor integration: Excellent plugins for VS Code, JetBrains, Vim, Emacs
- Widely adopted: Industry standard — most JavaScript projects use Prettier
- Plugin system: Community plugins for PHP, Java, SQL, Svelte, Astro, and more
Configuration
Most teams use defaults or a minimal .prettierrc:
{
"semi": false,
"singleQuote": true,
"trailingComma": "all",
"printWidth": 100
}
Limitations
- Performance can be slow on very large files or codebases (addressed by newer alternatives)
- Some formatting choices are controversial (the way Prettier wraps JSX, for instance)
- Does not catch errors or enforce code quality — purely formatting
Biome
Biome (successor to Rome) is a fast, Rust-based formatter and linter for JavaScript and TypeScript. It aims to replace both Prettier and ESLint with a single, faster tool.
Strengths
- Speed: 10-35x faster than Prettier due to Rust implementation
- Formatter + linter: One tool for both formatting and linting
- Prettier-compatible: Output is 97%+ compatible with Prettier — migration is nearly seamless
- Zero config: Works out of the box with sensible defaults
- Single dependency: Replaces Prettier + ESLint + multiple ESLint plugins
Limitations
- Fewer language support than Prettier (JS, TS, JSX, TSX, JSON, CSS — no HTML, Markdown, YAML yet)
- Smaller plugin ecosystem
- Fewer linting rules than ESLint (though growing rapidly)
- Newer tool — less battle-tested in enterprise environments
Best For
Teams that want faster formatting and want to consolidate Prettier + ESLint into a single tool. The speed improvement is noticeable in large monorepos.
Python
Black
Black calls itself "the uncompromising code formatter." It has almost zero configuration options by design. The only meaningful setting is line length (default 88).
Strengths
- Completely opinionated: One style, no debates, no configuration bikeshedding
- Deterministic: The same input always produces the same output, regardless of the original formatting
- AST-safe: Verifies that the AST is unchanged after formatting — your code's behavior is guaranteed to be preserved
- Widely adopted: Used by major Python projects (Django, pandas, pytest, FastAPI)
- Fast: Quick enough for format-on-save in editors
Configuration
Almost nothing to configure. A typical pyproject.toml:
[tool.black]
line-length = 100
target-version = ['py312']
That is it. That is the configuration.
Limitations
- Some formatting choices are unpopular (double quotes by default, magic trailing comma behavior)
- No option to change most formatting decisions — you accept Black's style or do not use it
- Does not sort imports (use isort or Ruff for that)
Ruff
Ruff is a Rust-based Python linter and formatter that has become the fastest-growing Python tool. Its formatter is Prettier-for-Python: AST-based, opinionated, and 10-100x faster than Black.
Strengths
- Speed: 10-100x faster than Black. Formats the entire CPython codebase in 0.3 seconds
- Linter + formatter: Replaces Black, isort, flake8, pyflakes, and dozens of other tools
- Black-compatible: Intentionally compatible with Black's output — easy migration
- Import sorting: Built-in isort-compatible import sorting
- Extensive rules: Over 800 linting rules from flake8, pylint, pycodestyle, and more
- Fix capability: Auto-fixes many linting issues, not just formatting
Limitations
- Some edge cases where output differs from Black
- Newer tool — some organizations are cautious about adoption
- Plugin system is limited compared to flake8
Best For
Any Python project. Ruff is strictly better than the combination of Black + isort + flake8 — faster, single dependency, compatible output. There is little reason not to adopt it for new projects.
Go
gofmt
gofmt is Go's official code formatter, included in the standard Go distribution. It is the gold standard for opinionated formatting — there are zero configuration options. Every Go file in the world is formatted identically.
Strengths
- Zero configuration: Nothing to decide, nothing to debate
- Universal adoption: Effectively 100% of Go code uses gofmt
- Built-in: Ships with Go — no additional installation
- Fast: Formats instantly
- Cultural norm: Not using gofmt in Go is a code smell — it is simply expected
goimports
goimports extends gofmt by also managing import statements — adding missing imports, removing unused ones, and grouping them properly.
Best Practice
Run goimports (which includes gofmt behavior) on save. Configure your editor to do this automatically.
Rust
rustfmt
rustfmt is the official Rust code formatter, included with the Rust toolchain. It is moderately configurable — more options than gofmt, fewer than clang-format.
Key Settings
# rustfmt.toml
max_width = 100
edition = "2024"
Strengths
- Official tool, ships with
rustup - Widely adopted across the Rust ecosystem
- Moderate configurability for the most debated options
- Fast formatting
- cargo fmt integrates with the build system
Limitations
- Some formatting decisions are contentious (particularly around where/how long match arms are handled)
- Some nightly-only options that are useful but unstable
C/C++
clang-format
clang-format is the standard C/C++ formatter from the LLVM project. It is highly configurable — the .clang-format file can have hundreds of options.
Strengths
- Comprehensive configuration for every formatting detail
- Preset styles: LLVM, Google, Chromium, Mozilla, WebKit, Microsoft
- Supports C, C++, Java, JavaScript, Objective-C, Protobuf, C#
- Editor integration for all major editors
- Widely used in large C++ codebases
Practical Advice
Start with a preset style and customize only what your team strongly disagrees with:
BasedOnStyle: Google
IndentWidth: 4
ColumnLimit: 120
Limitations
- Too many options can lead to configuration bikeshedding
- Some formatting choices cannot be expressed in the configuration
- Occasional surprising formatting for complex template code
Editor Integration Best Practices
Format on Save
Configure your editor to run the formatter automatically when you save a file. This is the single most important step — it makes formatting invisible and automatic.
VS Code settings.json:
{
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"[python]": {
"editor.defaultFormatter": "charliermarsh.ruff"
}
}
Pre-Commit Hooks
Use a pre-commit hook to catch any unformatted code before it reaches your repository:
# .pre-commit-config.yaml
repos:
- repo: https://github.com/pre-commit/mirrors-prettier
rev: v3.3.0
hooks:
- id: prettier
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.8.0
hooks:
- id: ruff-format
CI Enforcement
Run the formatter in check mode in CI to fail builds with unformatted code:
# JavaScript/TypeScript
prettier --check .
biome check .
# Python
ruff format --check .
# Go
gofmt -l . | grep . && exit 1
# Rust
cargo fmt --check
Recommendations by Language
| Language | Recommended Formatter | Runner-Up |
|---|---|---|
| JavaScript/TypeScript | Prettier (or Biome for speed) | Biome |
| Python | Ruff | Black |
| Go | gofmt/goimports | None needed |
| Rust | rustfmt | None needed |
| C/C++ | clang-format | None meaningful |
| Java | google-java-format | Spotless |
| Ruby | RuboCop | Standard |
| PHP | PHP-CS-Fixer | Pint (Laravel) |
The Bottom Line
The best code formatter is the one your team adopts and never thinks about again. Configure it once, set up format-on-save and CI enforcement, and redirect all formatting energy into writing better code.
If you are starting a new project in 2026: use Ruff for Python, Biome (or Prettier) for JavaScript/TypeScript, and the official formatter for Go, Rust, or any language that has one. The trend is clear — opinionated, fast, minimal-configuration formatters win because they eliminate a category of unproductive discussion entirely.