Boost Your Python Code Quality with Ruff
Over the years, as it became more professionalized, the Python ecosystem has gradually equipped itself with a multitude of static code analysis tools designed to help teams maintain code quality: Flake8, pylint, isort, Mypy, Pyright, Black, Bandit… These tools serve different purposes, from enforcing code style to detecting potential errors. However, using them simultaneously can sometimes slow down workflows and increase configuration complexity.
This is where ruff comes in, with the ambition of becoming a single tool to replace them all.
Introduced in 2022, ruff aims to replace existing linters and formatters, with a strong emphasis on execution speed, thanks to being written in Rust rather than Python. As of today, it already implements more than 800 checks, borrowed from Pyflakes, pycodestyle, mccabe, isort, pydocstyle, pyupgrade, Flake8 (and dozens of its plugins), Bandit, eradicate, Pylint, tryceratops, flynt, refurb, pydoclint… And as if that weren’t enough, it has also begun adding its own additional rules, particularly targeting popular frameworks such as FastAPI or NumPy.
Despite this large number of rules, it runs extremely fast, capable of analyzing most codebases in under a second. For instance, it scans the entire CPython codebase in just 160 ms, compared to nearly 12 s with Pyflakes and over a minute with Pylint.
On the formatting side, the Python ecosystem was already largely unified around Black, which gained popularity thanks to its radical approach: a formatter that enforces its own style with virtually no configuration options, thus sparing teams from long and often fruitless debates about formatting conventions. ruff follows the same principle and provides formatting that is nearly identical to Black (with intentional and well-documented differences), but with dramatically faster performance (literally!). It is also slightly more configurable, offering parameters that might help win over some teams: for example, it can be set to prefer single quotes over double quotes for strings, or to preserve the developer’s choice of quotation marks case by case. This directly addresses one of the main criticisms of Black: the enforcement of a single style.
It is also worth noting that many of ruff’s divergences remain backward-compatible with Black: ruff introduces modifications to code, but these modifications are accepted by Black, which won’t force a rollback. This makes it possible, in certain situations, to use both tools side by side, as I experienced on a project where developers began adopting ruff, while Black remained the standard in CI/CD workflows.
To ruff or not to ruff?

From a functional perspective, the decision to adopt ruff right now will largely depend on the tools you are currently using.
Not using a linter yet?
It’s time to introduce one into your software production pipeline! ruff is a smart choice here, since you won’t have to deal with inconsistencies compared to your current tools, and its outstanding performance will let you add it to your workflows without any significant impact on speed.
However, don’t get too ambitious at first: start by enabling only ruff’s default rules, and once your code is compliant, gradually add the rules that matter most to you. This way, you’ll avoid feeling overwhelmed by the heavy workload that adapting a long-established codebase might represent.
Do you mainly use Flake8 or similar tools?
Here again, switching to ruff is a smart move. You’ll gain in speed while maintaining excellent compatibility with your current setup.
Do you rely heavily on Pylint?
This is where the choice becomes more difficult. Although ruff has started to include some Pylint rules, it does not aim to fully replace it in the short term. Indeed, Pylint is more than just a linter: it also performs type checking (notably without relying heavily on annotations), something ruff has chosen not to implement for now.
If your codebase is properly typed, the solution may be to combine ruff for linting with Mypy for type checking.
If not, you may prefer to stick with Pylint. Another option is to compromise: use ruff in development environments for faster analysis, and Pylint in CI/CD pipelines for more comprehensive checks.
And what about formatting?
Whether you already use a formatter or not, replacing it with ruff can be attractive for its performance gains. That said, unlike Black, which guarantees identical execution before and after formatting (by rigorously comparing the produced ASTs), ruff does not currently offer such guarantees. There is therefore a slight risk when applying it to large codebases, even if its aim of producing code nearly identical to Black’s should minimize surprises.
Why not adopt ruff?
No tool is perfect, and there are valid reasons not to adopt ruff. These concern mainly its governance and the choice of the Rust language.
On governance: unlike most of the tools it aims to replace, ruff is not a purely community-driven project. It is developed under the umbrella of Astral, a New York–based company. While Astral seems genuinely committed to openness and to continuing to provide free, open-source tools, the question of its business model will inevitably arise.
Of course, the use of a very permissive license (MIT) ensures that, in case of divergence between Astral’s ambitions and the community’s will, a fork will always be possible. But here the choice of Rust raises questions: while it was necessary to achieve the desired performance, it makes forking harder, since many Python developers are not proficient in Rust. This drawback is tempered by Rust’s growing popularity in the Python community, where it is increasingly replacing C and C++ for high-performance libraries—examples include Pydantic (largely rewritten in Rust) and Hugging Face’s tokenizers.
Finally, there’s the issue of the future of existing tools. ruff draws heavily on them to grow quickly, but its success could threaten them by diverting their user bases. For this reason, it might be valuable for ruff’s governance to be shared in the future with the PSF and PyCQA, to help preserve the ecosystem’s accumulated expertise.
As for me, I have already adopted ruff in most of my projects, particularly at OBI Partner, though I remain cautious about the three points mentioned above. So, if you too are considering making the switch and need assistance, don’t hesitate to reach out.
Ready? pipx install ruff!