Code Qualitybeginner

Ruff vs Black vs Flake8

A comparison of Ruff, the Rust-based all-in-one Python linter and formatter, against Black for formatting and Flake8 for linting, covering speed, rule coverage, configuration, and migration path.

Quick Answer

Ruff replaces both Black and Flake8 with a single Rust binary that runs orders of magnitude faster and implements most of their rules. Black and Flake8 remain correct, stable choices, but Ruff is where new projects and most migrations land.

Reviewed by TechLogHub Engineering Team. Last updated October 15, 2026. Updated for Ruff's expanded rule coverage, formatter stability, and the changed maintenance picture after OpenAI's acquisition of Astral.

Feature comparison of Ruff vs Black vs Flake8
FeatureRuffBlackFlake8
Primary Role
Linter and formatter
Formatter only
Linter only
Implementation Language
Rust
Python
Python
Typical Runtime
Milliseconds on typical repos
10/10
Seconds on medium repos
6/10
Slowest — seconds to minutes with plugins
3/10
Autofix Support
Yes, for a large share of rules
Formatting only
Essentially none
Rule Coverage
Flake8, isort, pyupgrade, pydocstyle, and many plugins
9/10
N/A — not a linter
4/10
pyflakes, pycodestyle, mccabe, plus plugins
8/10
Configuration
pyproject.toml
pyproject.toml, minimal options by design
setup.cfg or .flake8
Editor Integration
Official LSP and VS Code extension
Widely supported in every major editor
Broad, long-established
License
MIT
MIT
MIT

Ruff

An extremely fast Rust-based Python linter and formatter from Astral that reimplements rules from Flake8, isort, pyupgrade, pydocstyle, and dozens of plugins in one tool.

Pros

  • Runs in a fraction of the time of the Python-based tools, fast enough for save-on-type
  • One tool replaces Flake8, isort, pyupgrade, pydocstyle, and a stack of plugins
  • Black-compatible formatter — same output style, no reformat churn on migration
  • Autofix for a large share of rules, not just detection
  • Configured entirely in pyproject.toml alongside everything else

Cons

  • A minority of niche Flake8 plugin rules still have no Ruff equivalent
  • Fast release cadence means rule behavior occasionally shifts
  • Rule namespace is large and can be overwhelming to configure from scratch
  • Now under OpenAI ownership via the Astral acquisition

Best For

Any new Python project, and any existing project where lint and format time is noticeable in CI or in the editor.

Black

The opinionated Python code formatter that ended formatting debates by offering essentially no configuration and one canonical output style.

Pros

  • The de facto formatting standard — its style is what the ecosystem expects
  • Deliberately unconfigurable, which eliminates style bikeshedding entirely
  • Extremely stable and predictable across releases
  • Community-governed under the Python Software Foundation umbrella
  • Huge base of existing CI configs and pre-commit hooks

Cons

  • Formatting only — you still need a separate linter
  • Noticeably slower than Ruff on large codebases
  • Some formatting decisions are divisive and cannot be overridden
  • Adds another Python dependency to your tooling environment

Best For

Projects that want the canonical Python formatting style with maximum stability, and teams not ready to consolidate tooling.

Flake8

The long-standing Python linter that wraps pyflakes, pycodestyle, and mccabe, extended through a large ecosystem of community plugins.

Pros

  • Enormous plugin ecosystem covering very specific and niche checks
  • Deeply understood — nearly every Python developer has used it
  • Extremely stable, with predictable behavior across years
  • Plugins let you enforce highly domain-specific conventions

Cons

  • Slowest of the three, especially with many plugins enabled
  • Detection only — almost no autofix capability
  • Uses setup.cfg or .flake8 rather than pyproject.toml by default
  • Plugin quality and maintenance vary widely
  • Largely superseded by Ruff for mainstream use cases

Best For

Projects that depend on specific Flake8 plugins with no Ruff equivalent, or legacy codebases where changing lint tooling isn't worth the diff.

Consolidation Beats Best-of-Breed Here

The historical Python setup layered Black for formatting, isort for imports, Flake8 plus half a dozen plugins for linting, and often pyupgrade on top. Each had its own config file, version pin, and pre-commit hook. Ruff's pitch is that these rules are mostly mechanical and there's no real benefit to having them live in four separate Python processes. In practice, teams that consolidate report the biggest win isn't speed but the disappearance of tool-version conflicts.

Black Compatibility Removes the Usual Migration Pain

The normal blocker to changing formatters is a repo-wide reformat that pollutes git blame. Ruff's formatter targets Black-compatible output, so switching produces little to no diff on an already-Black-formatted codebase. That makes the migration a config change rather than a code change — verify with a dry run on your largest package before committing.

Where Flake8 Plugins Still Matter

Ruff has reimplemented the rules from a wide range of Flake8 plugins, but the long tail is genuinely long, and some organization-specific or domain-specific plugins have no equivalent. The right check is mechanical: list your enabled plugins, map each against Ruff's rule table, and see what's left. If the gap is one or two rules you can live without, migrate. If it's a compliance-mandated check, keep Flake8 for that subset.

The Governance Footnote

Ruff and uv both come from Astral, which OpenAI acquired in March 2026. Both remain MIT-licensed and openly developed, and there has been no license change. Still, Black's independent community governance is a real differentiator for organizations with vendor-neutrality requirements, and it's a legitimate reason to keep Black even while adopting Ruff for linting.

Verdict

For new projects, use Ruff for both linting and formatting — it's faster, it's Black-compatible so the diff is clean, and it removes a tool from your stack. Keep Flake8 only if you depend on a plugin Ruff hasn't reimplemented, and keep Black only if your team specifically wants the reference formatter maintained independently of Astral.

Related Comparisons

All Comparisons

Ruff vs Black vs Flake8 — FAQ

Common questions answered from the comparison above

Can I use Ruff for linting and keep Black for formatting?

Yes, and it's a common intermediate step. Disable Ruff's formatter, use it purely as a linter, and let Black own formatting. You get most of the speed benefit on the lint side without touching your formatting pipeline.

Does Ruff replace mypy?

No. Ruff is a linter and formatter, not a type checker. It catches some type-adjacent issues but does not perform type inference across your codebase. You still need mypy, pyright, or ty for that.

Will switching to Ruff change my code formatting?

On a codebase already formatted with Black, the diff should be minimal to none since Ruff's formatter targets Black-compatible output. Run it in check mode across the repo first — if the diff is large, something in your Black config is non-default and needs mapping over.

Is Flake8 deprecated?

No. It's actively maintained and works fine. It has simply lost mainstream momentum to Ruff, which means new tutorials, new plugin development, and new project templates increasingly assume Ruff. That's an adoption trend, not an end-of-life notice.

How do I configure Ruff without getting lost in its rule set?

Start narrow. Enable the rule sets matching what you already run — typically pyflakes, pycodestyle, and isort equivalents — get the repo clean, then add rule families one at a time. Enabling everything at once on an existing codebase produces thousands of findings and kills momentum.

Get the next comparison by email

One email a week: new and trending developer tools, fresh comparisons, and what shipped. Unsubscribe in one click.