Ruff vs Black vs Flake8: 389x Faster Linting [2026]

Python developers spent a decade stitching together Black for formatting, Flake8 for style checks, isort for import order, and Pylint for deeper static analysis. In 2026, a single Rust-based tool called Ruff is replacing most of that stack, and the numbers behind the switch are hard to ignore. Astral’s own benchmark against the CPython codebase clocked Ruff at 389.73 times faster than Flake8 and 126.33 times faster than Pylint, while independent trackers now put Ruff’s monthly PyPI downloads at roughly 180 million, ahead of Black’s 134.9 million. This guide breaks down Ruff vs Black vs Flake8 with real 2026 version numbers, GitHub star counts, pricing, migration steps, and the specific scenarios where each tool still makes sense.

None of these three tools do exactly the same job, which is part of why the comparison gets confusing. Black only formats code. Flake8 only lints (checks style and catches simple bugs) by combining pyflakes, pycodestyle, and mccabe. Ruff does both, plus import sorting, plus a growing list of rule categories borrowed from Pylint, pyupgrade, autoflake, and even Bandit-style security checks. That overlap is exactly why so many teams are consolidating three or four tools into one in 2026.

Google · Preferred Sources

Don't miss new tech stories on Google

Add Tech Insider once in the Google app and our stories appear in your news suggestions.

Add Now

Ruff vs Black vs Flake8 at a Glance

Before diving into benchmarks and migration steps, here’s the short version. Ruff is a linter and formatter written in Rust by Astral, designed to be a drop-in replacement for Black, isort, Flake8 (with a modest plugin set), pyupgrade, and autoflake. Black is a pure formatter with no linting opinions of its own. Flake8 is a pure linter that has no formatting features and depends on separate tools for that job. If you’re comparing python linter options for a new project in September 2026, the practical question isn’t “which is best” in the abstract, it’s whether you need one consolidated tool (Ruff) or a modular stack you can swap piece by piece (Black plus Flake8 plus isort).

Ruff’s current stable release is 0.17.1, published in October 2026, with piwheels listing 18 separate release files for that version alone, a sign of how many platforms and Python versions Astral now builds for directly. Black sits at 26.5.1, released May 18, 2026. Flake8 is on 7.3.0, supporting Python 3.9 through 3.13 and maintained by the Python Code Quality Authority (PyCQA), a noticeably narrower range than Ruff, whose 0.17.0 release that same month advanced its syntax checker’s default target from Python 3.14 to Python 3.15, nine versions of coverage in total counting back to 3.7. All three remain free and open source, which means the “ruff vs black vs flake8” decision is really about speed, tooling consolidation, and how much configuration overhead your team is willing to carry.

What Is Ruff, and Why Is Everyone Switching?

Ruff is developed by Astral, the same company behind the uv package manager, and it’s written entirely in Rust rather than Python. That single design decision explains most of the performance gap in this comparison. Where Flake8 and Pylint run as interpreted Python processes that import your code and walk its abstract syntax tree in Python, Ruff compiles to native machine code and processes files in parallel across CPU cores.

According to Astral’s FAQ documentation, Ruff can serve as a drop-in replacement for Flake8 “when used without or with a small number of plugins,” alongside Black, on Python 3 codebases. It can also replace Black itself, isort, yesqa, eradicate, and most of the rules implemented in pyupgrade. Ruff’s catalog now spans more than 700 lint rules across the pyflakes (F), pycodestyle (E/W), import-sorting (I), pyupgrade (UP), and flake8-bugbear (B) rule families, and since the Ruff 0.16.0 release in July 2026, Astral enables 413 of those rules by default out of the box, up from just 59 previously, all configured from a single pyproject.toml file. That default-rule push kept accelerating: with the Ruff 0.17.0 release in October 2026, GitHub’s own tooling moved its default target version from Python 3.10 to Python 3.11, a sign that even platform-level integrations are now tracking Ruff’s release cadence closely rather than pinning to older defaults.

The project’s star count reached roughly 48,000 on GitHub in 2026, and later 2026 trackers put the repository at roughly 48,143 stars on the narrower astral-sh/ruff count used for direct tool comparisons (some trackers report closer to 100K+ when counting differently, so treat exact star figures as a snapshot rather than a fixed number). Monthly PyPI downloads sit around 180 million as of an April 2026 snapshot cited by multiple 2026 ecosystem write-ups, up from a fraction of that a year earlier. Adoption now extends well beyond PyPI’s own numbers, too: CERN’s own package repository lists Ruff 0.16.10, released in October 2026, as the latest available version, a notable signal that Rust-based tooling has reached even conservative scientific-computing environments; PyPI’s own listing for that same 0.16.10 build includes a 10.3-MB macOS x86-64 wheel, underscoring how much platform-specific binary weight Astral now ships with every release. Ruff is licensed under MIT.

What Is Black? The Formatter That Started the “Opinionated” Trend

Black, maintained by the Python Software Foundation, popularized the idea of a formatter with almost no configuration options. Feed it Python code and it rewrites indentation, quote style, and line length according to a fixed style guide, removing the “tabs vs spaces” style of argument from code review entirely. Black requires Python 3.10 or newer to run (though it can format code targeting older Python versions) and is distributed under the MIT license.

Black’s current stable release is 26.5.1, published May 18, 2026. The repository carries approximately 41,578 to 41,829 GitHub stars depending on which 2026 snapshot you check, and pepy.tech reports Black has been downloaded more than 3.1 billion times in total, including roughly 150.6 million downloads in the last 30 days as of its most recent count. A separate 2026 comparison table puts Black’s monthly PyPI downloads closer to 134.9 million, a gap that reflects different measurement windows rather than contradictory data.

What Black does not do is catch bugs. It has no concept of unused imports, undefined names, or overly complex functions. Teams running Black in isolation still need a separate linter, which is exactly the gap Flake8 and, more recently, Ruff’s formatter mode were built to fill or replace.

What Is Flake8? The Old Guard of Python Linting

Flake8 has been the default Python linter for over a decade, and it works by wrapping three separate tools under one command: pyflakes for logic errors (unused imports, undefined variables), pycodestyle for PEP 8 style violations, and mccabe for cyclomatic complexity checks. Its real strength is the plugin ecosystem, hundreds of community-maintained Flake8 plugins exist for everything from docstring conventions to security scanning, and large enterprise codebases often carry years of accumulated plugin configuration that’s expensive to replicate elsewhere.

Flake8’s current version is 7.3.0, maintained by PyCQA and supporting Python 3.9 through 3.13. GitHub star counts sit far below Ruff and Black, in the range of 3,766 to 3,816 stars depending on the tracker, though star count understates Flake8’s real footprint since so much of its usage comes through plugins rather than the core package. Zaira Labs’ 2026 tool tracker records Flake8 at roughly 55.4 million monthly downloads, and a separate PyPI download leaderboard shows a close 46.9 million over a 30-day window.

Flake8 does not read configuration from pyproject.toml natively, teams configure it through a dedicated .flake8 file, or sections inside setup.cfg or tox.ini. That’s a meaningful friction point compared to Ruff and Black, both of which centralize configuration in the same TOML file most modern Python projects already use for packaging metadata.

Full Specs Comparison: 12 Data Points

The table below lines up Ruff, Black, and Flake8 side by side, with Pylint and isort included where the data helps explain what Ruff is actually consolidating.

MetricRuffBlackFlake8
Current stable version0.16.10 (Oct 2026)26.5.1 (May 18, 2026)7.3.0
Core languageRustPythonPython
GitHub stars (2026 snapshot)~48,143~41,578–41,829~3,766–3,816
Monthly PyPI downloads~180M~134.9M–150.6M~46.9M–55.4M
LicenseMIT (Astral)MIT (PSF)MIT-style (PyCQA)
What it doesLint + format + import sort (700+ rules)Format onlyLint only (pyflakes + pycodestyle + mccabe)
Config filepyproject.toml [tool.ruff]pyproject.toml [tool.black].flake8 / setup.cfg / tox.ini
ReplacesBlack, isort, Flake8, pyupgrade, autoflakeN/A (formatter only)pyflakes, pycodestyle, mccabe
Auto-fix supportYes, ruff check –fixYes, rewrites files in placeNo, report-only unless paired with plugins
Plugin ecosystemNative rule sets, growingNone (single purpose)Hundreds of third-party plugins
Official VS Code extensionYes (Ruff extension)Yes (Black Formatter extension)Yes, via Python extension
Minimum Python to run tool itselfNone (standalone Rust binary)Python 3.10+Python 3.9+

Benchmark Results From 5 Independent Sources

Every serious comparison of these three tools comes down to the same question: how much faster is Ruff, really? The most cited figure comes directly from Astral’s own published benchmark against the CPython codebase, a large, real-world Python project that stresses a linter’s parsing and rule-evaluation performance. Ruff completed the run in 297.9 milliseconds (mean, 10 runs), a number small enough that it barely registers on a developer’s save-and-check workflow, compared to tools that can take several seconds on the same codebase. Measured against that baseline:

  • Ruff is 389.73 times faster than Flake8
  • Ruff is 226.35 times faster than pycodestyle alone
  • Ruff is 137.46 times faster than pyflakes alone
  • Ruff is 126.33 times faster than Pylint
  • Ruff is 38.81 times faster than autoflake

That benchmark is repeatedly cited across 2025 and 2026 comparison guides as still representative of the performance gap, even though the original test predates this article. More recent, independently reported figures back up the same conclusion from different angles. Astral’s own blog states that Ruff’s formatter runs “over 30 times faster than existing tools, while maintaining more than 99.9% compatibility with Black,” meaning teams can switch formatters without a wave of unrelated diff noise in their next pull request.

A 2026 Python ecosystem deep-dive from developer Ismat Samadov reported that Ruff pulls approximately 180 million monthly PyPI downloads, describing it as “even bigger by raw download numbers” than the modern uv package manager, which itself passed 126 million monthly downloads and over 82,600 GitHub stars, “surpassing Poetry’s roughly 75 million.” A separate scientific-computing tooling guide from matforge.org frames the real-world impact in workflow terms rather than raw milliseconds, stating that Ruff “replaces Black (formatting), isort (import sorting), Flake8 (style checks), pyupgrade (dead-code removal), and autoflake (unused variable removal) in a single binary that runs 10 to 100 times faster” than running each tool separately in sequence. And a 2026 migration handbook from pydevtools.com reports that a full migration on a 47,000-line codebase typically takes 1 to 2 hours, covering config translation, auto-fix application, and CI updates, a concrete number that matters more to engineering managers than raw millisecond counts.

Pricing and Licensing Breakdown

All five tools in this comparison are free to use, which simplifies the “pricing” question considerably compared to most developer tool comparisons. The differences that matter are licensing terms and whether a commercial entity sits behind ongoing development.

ToolCostLicenseBacking organization
RuffFreeMITAstral (VC-funded company)
BlackFreeMITPython Software Foundation
Flake8FreeMIT-stylePyCQA (community)
PylintFreeGPL-2.0pylint-dev (community, Tidelift funding)
isortFreeMITPyCQA (community)

Ruff is the only tool here with a for-profit company behind it. Astral, which also builds the uv package manager and the ty type checker, has not published a public enterprise pricing page for Ruff as of September 2026, and none of the 2025-2026 sources reviewed for this comparison list specific subscription costs. The core linter and formatter remain free and MIT-licensed with no feature gating. Pylint is worth flagging separately because it’s GPL-2.0 rather than MIT, which matters if your organization has policies restricting copyleft-licensed build tooling, even though Pylint is typically invoked as a standalone process rather than linked into shipped code.

What Each Tool Actually Checks: Rules and Coverage

The “ruff vs flake8” question really comes down to rule coverage. Flake8’s core install checks three categories: pyflakes catches logic errors like unused imports and undefined names, pycodestyle enforces PEP 8 formatting rules (the E and W codes), and mccabe flags functions that exceed a configurable cyclomatic complexity threshold. Anything beyond that, docstring conventions, security scanning, Django-specific checks, requires installing a separate Flake8 plugin, and large teams often accumulate a dozen or more.

Ruff’s rule set is organized into prefixed categories that map directly onto the tools it replaces: E and F codes mirror pycodestyle and pyflakes, I codes handle isort-compatible import sorting via the [tool.ruff.lint.isort] config block, UP codes implement pyupgrade’s code-modernization checks, and B codes cover flake8-bugbear-style correctness bugs. According to a 2026 Python ecosystem write-up, Ruff now unifies more than 700 rules drawn from Black, isort, Flake8, and Pylint into a single binary. That doesn’t mean Ruff replicates every Pylint check, Pylint performs deeper semantic analysis by actually inferring code behavior, which is part of why it remains slower and why some teams keep it running as a secondary, less-frequent check even after adopting Ruff for everyday linting.

Black, by contrast, has zero linting rules. It only rewrites formatting: line length, string quote style, trailing commas, and whitespace. Ruff’s formatter is explicitly built to be a “drop-in replacement for Black,” according to Astral’s FAQ, and produces output that’s more than 99.9% identical to what Black would generate on the same file, provided the line-length setting matches between the two.

Ruff’s Rule Prefixes Explained

One detail that trips up teams new to Ruff is the rule-code system. Every violation Ruff reports carries a letter prefix that tells you which legacy tool that check originally came from, which makes migrating an existing Flake8 or Pylint configuration much easier once you know the mapping. Rather than learning an entirely new rule taxonomy, most of Ruff’s codes are direct ports of codes teams already recognize from years of Flake8 output.

PrefixOrigin toolWhat it checksExample rule
E / WpycodestylePEP 8 style violationsE501 (line too long)
FpyflakesLogic errorsF401 (unused import)
IisortImport sorting and groupingI001 (unsorted imports)
UPpyupgradeOutdated syntax patternsUP035 (deprecated typing import)
Bflake8-bugbearLikely bugs and design smellsB006 (mutable default argument)
C90mccabeCyclomatic complexityC901 (function too complex)
Sflake8-banditSecurity-related checksS101 (use of assert)

This prefix system is also why the migration guides referenced throughout this article can offer such specific mapping instructions: a team auditing its old .flake8 file can match each ignored code to the equivalent Ruff prefix almost mechanically, rather than re-deriving a lint policy from scratch. Teams that previously ran flake8-bugbear or flake8-bandit as separate plugin installs often find those checks are already available natively inside Ruff once the corresponding prefix is added to the select list.

Where isort and Pylint Still Fit in a Ruff World

It’s tempting to read the Ruff download numbers and conclude isort and Pylint are on their way out entirely, but the 2026 data doesn’t fully support that. isort still pulls roughly 143 to 145 million monthly PyPI downloads, a figure that’s stayed high in part because so many projects pin isort as a transitive dependency of other tools, and in part because teams running Ruff’s I-prefixed import rules in check-only mode (without the format step) sometimes keep isort around for edge cases in unusual import layouts that predate their migration.

Pylint’s case is more substantive. Its 55.8 to 65 million monthly downloads (depending on which 2026 tracker you check) reflect real, ongoing use, mostly because Pylint’s static analysis engine actually infers what code does rather than just pattern-matching against syntax. That lets it catch classes of bugs, like a method that references an attribute that doesn’t exist on the object it’s called against, that Ruff’s current rule engine doesn’t attempt. Several 2026 comparison guides describe the practical pattern as running Ruff on every commit for speed, then running Pylint on a slower cadence, nightly builds, weekly scans, or pre-release checks, to catch the smaller set of deeper issues Ruff isn’t designed to find. That’s a meaningfully different relationship than the one Ruff has with Black or Flake8, where the overlap in what the tools actually check is close enough that most teams pick one and drop the other entirely.

Common Pitfalls When Switching to Ruff

Most Ruff migrations documented in 2026 guides go smoothly, but a handful of recurring issues show up often enough to flag before you start.

  • Assuming default rule selection matches your old Flake8 config. Ruff ships with a conservative default rule set. If your team relied on a large Flake8 plugin stack, you need to explicitly add each equivalent prefix to select, it won’t happen automatically just by installing Ruff.
  • Skipping the formatter compatibility check. Astral states Ruff’s formatter is more than 99.9% Black-compatible, not 100%. Run ruff format --diff against a Black-formatted branch before merging to catch the rare edge case where output differs, particularly around complex nested f-strings.
  • Forgetting plugin-only checks have no Ruff equivalent yet. As the PyPI Warehouse migration shows, some custom or niche Flake8 plugins genuinely have no Ruff replacement. Audit your plugin list before assuming a 100% replacement is possible.
  • Not pinning the Ruff version in CI. Because Ruff ships new stable lint rules and formatter style changes fairly often (Astral’s v0.15.0, released February 2026, alone added sixteen new stable rules, a new formatter style guide, and claimed speedups of tens to hundreds of times over running individual tools separately), an unpinned Ruff version in CI can introduce unexpected new failures on an otherwise unchanged codebase after a routine dependency update. That churn is ongoing rather than a one-time event: Ruff 0.16.2, shipped in August 2026, included a fix for false positives in rule PYI041, according to a DevUpdate release write-up, and the following point release, 0.16.5, landed on August 27, 2026 per Astral’s own changelog, underscoring how quickly rule behavior can shift between minor versions.

Real-World Examples: Who’s Actually Using What

Public migration write-ups give a clearer picture than adoption surveys, since most companies don’t publish detailed linter-stack breakdowns. Here are five documented, source-backed examples from 2025-2026.

  • PyPI’s Warehouse codebase. A 2026 migration guide from pydevtools.com states that the Warehouse project, the Python Software Foundation’s own package-index infrastructure, “migrated to Ruff in April 2026, retiring Black, isort, pyupgrade, and most Flake8 plugins,” while keeping Flake8 installed only for one internal, custom-prefixed plugin that Ruff doesn’t replicate. That’s a rare case of PSF-adjacent infrastructure documenting an exact migration month.
  • pytest-bdd. A GitHub pull request against the pytest-bdd project (#758), still referenced in 2026 tooling guides, shows the maintainers migrating flake8, isort, pydocstyle, and pyupgrade to Ruff in a single change, collapsing four separate config blocks into one.
  • Modern scientific Python stacks. A 2026 tooling guide from matforge.org, aimed at scientific computing teams, recommends a combined uv plus Ruff plus ty stack as the default for new projects, explicitly citing the 10 to 100 times speedup over running Black, isort, Flake8, pyupgrade, and autoflake in sequence during CI.
  • CI/CD pipelines still running Flake8 directly. Not every team has moved on. A 2026 CI/CD pipeline guide from nevercodealone.de documents Flake8 7.3.0 running in a live pipeline configuration, underscoring that Flake8’s plugin-based, incremental-adoption model still has a place in codebases that can’t justify a full toolchain swap.
  • Migration handbook demand itself. The existence and specificity of pydevtools.com’s step-by-step “How to replace Black, isort, flake8, and pyupgrade with Ruff” handbook, complete with rule-prefix mapping tables and pre-commit hook updates, is itself a signal: enough teams are running this exact migration in 2026 that dedicated reference material has become worth publishing and maintaining.

Migration Guide: Moving From Black + isort + Flake8 to Ruff

If your team is consolidating an existing Black, isort, and Flake8 setup into Ruff, the process is more mechanical than risky, most of the effort is translating configuration, not rewriting code. Here’s the sequence documented across 2026 migration guides.

  1. Install Ruff alongside your existing tools first: pip install ruff or uv add --dev ruff. Don’t remove Black or Flake8 yet.
  2. Audit your current configuration: list every setting in [tool.black], your .flake8 file, and [tool.isort].
  3. Create a [tool.ruff] block in pyproject.toml and set line-length to match your existing Black configuration (default 88).
  4. Add a [tool.ruff.lint] section and set select to the rule families you need, typically starting with ["E", "F", "I", "UP", "B"] to cover pycodestyle, pyflakes, isort, pyupgrade, and bugbear-style checks.
  5. Port any per-file ignores from your .flake8 file into Ruff’s [tool.ruff.lint.per-file-ignores] table.
  6. Add a [tool.ruff.lint.isort] block if your isort config used custom section ordering or first-party module detection.
  7. Run ruff format . and diff the output against your last Black-formatted commit, Astral’s stated compatibility target is over 99.9% identical output.
  8. Run ruff check --fix . to auto-fix the lint violations Ruff can resolve automatically, then manually review anything left flagged.
  9. Update your pre-commit hooks and CI pipeline to call ruff check . and ruff format --check . instead of separate black, isort, and flake8 invocations.
  10. Uninstall the old tools once CI is green: pip uninstall black isort flake8 autoflake pyupgrade, unless, like the Warehouse project, you still need Flake8 for a specific plugin Ruff hasn’t replicated.

Here’s a minimal starting configuration block referenced across multiple 2026 migration guides:

[tool.ruff]
line-length = 88
target-version = "py312"

[tool.ruff.lint]
select = ["E", "F", "I", "UP", "B"]

[tool.ruff.lint.isort]
known-first-party = ["your_package_name"]

[tool.ruff.format]
quote-style = "double"

Per the pydevtools.com handbook, this whole process, including auditing, config translation, running fixes, and updating CI, typically takes about 1 to 2 hours on a codebase in the 47,000-line range. Larger monorepos with heavy plugin dependence will take longer, mostly in step 5, mapping obscure Flake8 plugin behavior onto Ruff’s native rule set or accepting that a small number of checks stay on Flake8 permanently.

Pros and Cons of Each Tool

Ruff

  • Pros: Dramatically faster (order of magnitude or more) than any single Python-based alternative, consolidates linting, formatting, and import sorting into one binary and one config block, active development from a funded company, official VS Code extension with format-on-save support.
  • Cons: Doesn’t replicate every Pylint semantic check, younger project with a faster-moving rule set that occasionally changes default behavior between minor versions, backed by a for-profit company whose long-term monetization plans for the ecosystem aren’t fully public yet.

Black

  • Pros: Zero-decision formatting ends style debates in code review, extremely stable and predictable output, backed by the Python Software Foundation, enormous existing install base and documentation.
  • Cons: Formatting only, still needs a separate linter, meaningfully slower than Ruff’s formatter on large codebases per Astral’s published benchmarks.

Flake8

  • Pros: Enormous, mature plugin ecosystem covering nearly any custom check a large enterprise codebase has accumulated, no formatting opinions to fight with, well understood by nearly every Python developer.
  • Cons: Slowest of the three tools by a wide margin in Astral’s CPython benchmark, no auto-fix in the core tool, configuration lives outside pyproject.toml, no built-in formatter.

6 Use Cases and Which Tool Fits Best

  • New FastAPI, Django, or Flask microservice starting from scratch: Ruff. A single dependency and a single config block cover linting, formatting, and import order, and CI runs finish faster on every commit.
  • Large legacy enterprise codebase with a dozen Flake8 plugins already tuned over years: Keep Flake8 for the checks Ruff doesn’t cover, but consider running Ruff alongside it for formatting and the rule families it does replicate, the approach the Warehouse project took by keeping one internal Flake8 plugin.
  • Team that only wants consistent formatting with no linting opinions: Either Black or ruff format, since Ruff’s formatter targets more than 99.9% Black-compatible output, this is largely a speed decision at this point.
  • Scientific computing or data science codebase: The uv plus Ruff combination recommended in 2026 scientific-tooling guides, since large notebooks-to-scripts codebases benefit disproportionately from Ruff’s parallel processing speed.
  • Codebase needing deep semantic bug detection beyond style, such as detecting a method that could raise an exception no caller handles: Pylint, run less frequently (e.g., nightly CI or pre-release) since it remains far slower than Ruff even though Ruff covers many of the same rule categories.
  • Large monorepo with slow CI and cost-sensitive compute: Ruff, purely on the CI time-and-cost math, replacing a multi-tool pipeline step with one fast binary reduces both wall-clock time and the compute minutes billed for it.

A handful of these use cases deserve one more layer of nuance. The “large legacy codebase” scenario is rarely all-or-nothing in practice: teams frequently run a phased rollout where Ruff’s formatter goes in first (since formatter changes are the lowest-risk, most mechanical part of a migration), followed weeks or months later by gradually expanding the select list in [tool.ruff.lint] rule family by rule family, rather than flipping every check on at once and triaging a wall of new warnings. And for the monorepo case specifically, the CI cost math compounds: a monorepo running separate Black, isort, and Flake8 steps across dozens of packages multiplies whatever per-package overhead each tool carries, so the relative savings from consolidating onto Ruff tend to scale with repository size rather than staying constant.

IDE and CI/CD Integration

Ruff ships an official VS Code extension that can be set as the default formatter with format-on-save enabled, a configuration explicitly documented in 2026 migration checklists. That extension handles both linting diagnostics and formatting in one install, replacing what used to require separate Black and Flake8 extensions running side by side. Black and Flake8 both retain long-standing, mature support inside VS Code’s Python extension and PyCharm’s built-in inspections and external tools configuration, so neither is losing editor support, they simply require managing two or three extensions instead of one.

For CI/CD, the practical difference shows up in pipeline YAML length and execution time. A legacy pipeline calling black --check ., isort --check ., and flake8 . as three sequential steps becomes two Ruff invocations, ruff check . and ruff format --check ., and per the benchmarks cited above, each of those steps finishes in a fraction of the time. Pre-commit configurations follow the same pattern: Astral publishes an official ruff-pre-commit hook that replaces separate Black, isort, and Flake8 hook entries with two hook IDs.

The Verdict: Which Should You Choose in 2026

For any Python project starting today, Ruff is the more defensible default. It’s free, MIT-licensed, roughly two orders of magnitude faster than Flake8 in Astral’s own CPython benchmark, and its formatter output matches Black closely enough (over 99.9% per Astral’s stated figure) that switching rarely produces a disruptive wall of reformatting diffs. The download numbers back up the trend line: Ruff’s roughly 180 million monthly PyPI downloads have pulled ahead of Black’s 134.9 to 150.6 million, its GitHub star count passed Black’s sometime in the second half of 2025 according to multiple 2026 trackers, and the project shows no sign of slowing its release cadence, with version 0.17.1 shipping in October 2026 alone.

That doesn’t make Black or Flake8 obsolete. Black remains a completely reasonable, extremely stable choice if a team specifically wants a formatter with zero linting responsibilities and doesn’t care about the speed gap on a small-to-medium codebase. Flake8 remains the right call anywhere a specific plugin has no Ruff equivalent, which is still common in large, plugin-heavy enterprise setups, exactly the pattern PyPI’s own Warehouse project followed by keeping one Flake8 plugin alive after an otherwise complete migration to Ruff in April 2026. The realistic 2026 pattern for most teams is Ruff by default, with Flake8 kept alive only for the specific checks it doesn’t yet cover.

If you’re starting a brand-new project this week, the decision tree is short: install Ruff, configure the E, F, I, UP, B rule families, and set ruff format as your formatter. If you’re maintaining an established codebase with years of Flake8 plugin configuration, don’t treat this as an urgent rip-and-replace. Run the audit steps in the migration guide above, confirm which plugins (if any) lack a Ruff equivalent, and move at whatever pace keeps CI green. The performance gap between these tools isn’t going to close, Ruff’s Rust-based architecture is a structural advantage that a Python-based tool can’t easily match, but there’s no penalty for migrating deliberately instead of all at once.

Frequently Asked Questions

Is Ruff a replacement for Black, or does it work alongside it?

Both are possible. Ruff includes its own formatter (ruff format) that Astral describes as a drop-in replacement for Black, producing output that’s more than 99.9% identical on matching configuration. Teams can also keep using Black for formatting while adopting only Ruff’s linting rules, though most 2026 migration guides recommend consolidating onto Ruff’s formatter too, since running two formatters invites conflicting output.

Does Ruff replace Pylint completely?

Not entirely. Ruff’s rule set overlaps significantly with Pylint’s more common checks, and Astral’s own materials describe Ruff as unifying rules drawn from Black, isort, Flake8, and Pylint. But Pylint performs deeper semantic inference than Ruff’s current rule engine, so some teams keep Pylint running as a secondary, less frequent check (for example, only in a nightly build) rather than removing it entirely.

What is the actual speed difference between Ruff and Flake8?

In Astral’s published benchmark against the CPython codebase, Ruff completed the run in a mean of 297.9 milliseconds, measured at 389.73 times faster than Flake8 on the same hardware and codebase. Broader 2025-2026 guides describe the real-world impact as a 10 to 100 times speedup when replacing a full Black plus isort plus Flake8 plus pyupgrade pipeline with Ruff alone.

Can Flake8 read configuration from pyproject.toml?

No. Flake8 does not natively support pyproject.toml configuration as of its 7.3.0 release. Teams configure it through a dedicated .flake8 file, or through [flake8] sections in setup.cfg or tox.ini. This is one of the practical frictions that pushes teams toward Ruff, which centralizes configuration in pyproject.toml alongside packaging metadata.

Is Ruff free for commercial use?

Yes. Ruff is MIT-licensed and free to use in commercial projects with no feature restrictions. Its developer, Astral, is a venture-funded company that also builds the uv package manager, but as of September 2026 there is no published enterprise pricing tier or paid feature gate for Ruff itself.

How long does migrating an existing project to Ruff take?

According to a 2026 migration handbook from pydevtools.com, a typical migration on a codebase around 47,000 lines takes roughly 1 to 2 hours, covering configuration translation, running auto-fixes, and updating CI and pre-commit hooks. Codebases with heavy, uncommon Flake8 plugin usage will take longer during the rule-mapping step.

Does Ruff support auto-fixing lint violations?

Yes. Running ruff check --fix automatically resolves the subset of violations Ruff knows how to safely rewrite, such as unused imports or import ordering. Flake8’s core tool has no auto-fix capability on its own; some Flake8 plugins add limited auto-fix behavior, but it isn’t a built-in feature of the base tool the way it is in Ruff.

Which tool has more GitHub stars in 2026?

Ruff, with roughly 48,143 stars on the astral-sh/ruff repository per a September 2026 snapshot, ahead of Black’s 41,578 to 41,829 stars. Flake8 trails both at roughly 3,766 to 3,816 stars, though its usage is spread across hundreds of separate plugin repositories that aren’t reflected in the core package’s star count.

Do I still need isort if I’m using Ruff?

Generally no. Ruff’s I-prefixed rules, configured through [tool.ruff.lint.isort], replicate isort’s core behavior, alphabetizing imports and grouping them into standard-library, third-party, and first-party sections. Teams with heavily customized isort configurations (unusual section definitions, custom sorting orders) should verify their exact setup translates cleanly before dropping isort, but for the vast majority of projects, Ruff’s import rules are a complete replacement.

Does switching to Ruff mean I lose Flake8’s plugin ecosystem entirely?

Not necessarily. Ruff natively covers the most widely used Flake8 plugin categories, bugbear-style checks, security scanning, complexity limits, docstring conventions, but it doesn’t reimplement every plugin that exists in Flake8’s ecosystem. The documented pattern from the PyPI Warehouse migration is to run Ruff for everything it covers and keep Flake8 installed solely for the small number of custom or niche plugins that have no Ruff equivalent, rather than treating it as an all-or-nothing decision.

Nadia Dubois

Nadia Dubois

AI & Innovation Editor

Nadia Dubois is the AI & Innovation Editor at Tech Insider, where she tracks the rapid evolution of artificial intelligence, from foundation models to real-world enterprise deployment. She previously covered AI and startups for La Tribune and contributed to MIT Technology Review's European coverage. Nadia specializes in generative AI, AI regulation, and the intersection of technology and European industrial policy. She holds a dual degree in Computational Linguistics and Journalism from Sciences Po Paris.

View all articles