mypy vs pyright: Two Checkers, One Pipeline, and a Speed Surprise

mypy catches 57% of type errors by default; pyright catches 97%. But mypy 2.1 now outruns pyright on batch CI. Here is the full 2026 breakdown.

Updated 13 min read
Python code on a screen — mypy vs pyright comparison

Pyright wins for new Python projects and VS Code users: it catches 97% of type errors by default and powers Pylance for real-time editor feedback. For Django, SQLAlchemy, and Pydantic-heavy codebases, mypy wins: its plugin ecosystem catches errors pyright misses. And the speed narrative has completely reversed: a June 2026 benchmark shows mypy 2.1.0 running Rich (38K LOC) in 0.90s vs pyright's 2.64s.

The widely-cited "pyright is 3-5x faster" claim predates mypy's mypyc-compiled builds. Pyright checks all code via type inference by default; mypy silently skips unannotated functions unless you add --check-untyped-defs or --strict. That behavioral default explains most of the 40-point error-detection gap between the two tools, which you'll see reflected across performance, type accuracy, editor integration, plugin ecosystem, CI/CD setup, and pricing below.

Key Takeaways

  • Pyright is best for new Python projects, VS Code users, and teams wanting maximum type accuracy out of the box
  • mypy is best for Django, SQLAlchemy, and Pydantic v1 projects, where its plugin ecosystem provides framework-specific accuracy pyright can't match
  • Pyright catches 97% of type errors by default vs mypy's 57%; the gap is largely explained by mypy skipping unannotated functions
  • mypy 2.1.0 (mypyc-compiled) is now 2-3x faster than pyright on batch CI; the old speed claim has reversed
  • Running both tools is a documented, production-proven pattern: pyright in the editor, mypy in CI

mypy vs pyright: At a Glance

Feature

mypy

pyright

Best For

Django/SQLAlchemy/Pydantic projects

New projects, VS Code users

Pricing

Free, open-source (MIT)

Free, open-source (MIT)

Language

Python + mypyc (C extension)

TypeScript / Node.js

Batch CI Speed

0.90s (Rich 38K LOC, June 2026)

2.64s (same benchmark)

Typing Spec Conformance

59.6% (84/141 tests)

95.7% (135/141 tests)

Error Detection (default)

57% (34/60 errors caught)

97% (58/60 errors caught)

Editor Integration

dmypy daemon, third-party LSP

Native LSP, powers Pylance

Plugin Ecosystem

Mature (django-stubs, sqlalchemy-stubs)

Limited (stubs only, no plugin API)

Unannotated Code

Skipped by default

Checked via inference by default

CI Installation

pip install mypy (no Node.js)

npm wrapper + Node.js required

Monthly PyPI Downloads

~159M

~35M

GitHub Stars

20,489

15,482

What Is mypy?

mypy type checker homepage

mypy is a static type checker for Python, created in 2012 by Jukka Lehtosalo as a Cambridge PhD project. Dropbox funded its early development (Guido van Rossum joined the mypy team after leaving Google), and it remains the most widely deployed type checker, with ~159M monthly PyPI downloads as of June 2026.

mypy is written in Python and compiled to a C extension via its own mypyc compiler. It uses a multi-pass analysis model: parsing, type collection, and type checking run in sequence, iterating until types converge. By default, mypy skips any function that lacks type annotations: a deliberate design choice for incremental adoption, and the direct source of its 57% default error-catching rate versus pyright's 97%.

Strengths

  • Mature plugin ecosystem: django-stubs, sqlalchemy-stubs, and the Pydantic v1 plugin provide deep ORM-aware type accuracy that no other checker currently matches
  • pip-installable, no Node.js: installs anywhere Python does, with no external runtime dependency, critical for reproducible CI pipelines
  • Gradual adoption model: skipping unannotated functions by default lets teams enable strict checking incrementally per module via [[tool.mypy.overrides]]

Weaknesses

  • Low default error detection: without --check-untyped-defs or --strict, mypy catches only 57% of type errors in partially-annotated codebases
  • No native language server: editor integrations exist but require manual daemon setup and produce rougher feedback than Pylance
  • Spec conformance gaps: mypy passes 59.6% of the python/typing conformance suite, with known gaps in narrowing, generic handling, and `new` support

What Is pyright?

pyright type checker on GitHub

Microsoft built Pyright as a static type checker for Python, releasing it in 2019. Eric Traut (Microsoft Principal Engineer) is the primary maintainer. Pyright ships near-weekly updates (491 total releases since March 2019) and powers Pylance, the official VS Code Python extension with tens of millions of active users.

Pyright is written in TypeScript and runs on Node.js. It uses a lazy JIT evaluation model, computing types on demand, skipping checks not needed in the current context, and re-checking only changed code incrementally. That architecture was designed from the start as a language server foundation, making completions, hover types, go-to-definition, rename refactoring, and auto-imports first-class requirements rather than add-ons.

Strengths

  • Best-in-class type accuracy: 95.7% conformance on the python/typing conformance suite, catching 97% of type errors by default
  • Native LSP and IDE integration: ships as both a CLI and the Pylance engine, providing sub-100ms real-time type feedback in VS Code without daemon configuration
  • Checks unannotated code by default: type inference covers all functions regardless of annotation coverage, surfacing errors mypy silently skips

Weaknesses

  • Node.js CI dependency: cannot be declared as a native Python dependency in pyproject.toml; the PyPI package installs a Node.js binary wrapper, complicating pure-Python CI pipelines
  • No plugin API for framework patterns: ORM metaclasses and dynamic typing in Django/SQLAlchemy generate real false positives that mypy plugins handle correctly
  • Younger issue history: 294 open issues vs mypy's 3,133; pyright is actively maintained, but its lower count partly reflects its 2019 birth year rather than superior quality

Performance: mypy vs pyright

The most repeated claim in Python type-checking circles is wrong. "Pyright is 3-5x faster than mypy" was accurate before mypy's mypyc-compiled builds but no longer holds as of 2026.

A June 2026 benchmark from pydevtools.com (Apple Silicon, median of 5 runs, caches cleared) shows the opposite:

Codebase

mypy 2.1.0

pyright 1.1.410

Rich (38K LOC)

0.90s

2.64s

SQLGlot (76K LOC)

2.58s

4.04s

mypy 2.1.0 is 2-3x faster on batch CI runs. This is not a one-off result: an earlier April 2026 run from the same benchmarking project showed the same direction, with mypy outperforming pyright on cold-start batch checks. The --num-workers flag added in mypy 2.0 enables parallel analysis (though real-world speedup on mid-sized projects is ~1.3x, not the 5x cited in release notes for million-line codebases).

The picture is different in editor mode. Pyright's lazy JIT architecture handles incremental re-checks (line-level changes via LSP) in under 100ms; mypy has no native language server, so editor integrations invoke it on save or via dmypy, adding perceptible latency. Result: mypy wins batch CI, pyright wins interactive editor.

At extreme scale, a different story: Charlie Marsh (@charliermarsh) of Astral reported that on a real >15M-line Python codebase, mypy took 38 minutes and pyright crashed out of memory.

During development, we've been running ty over a (real) >15 million line-of-code Python application. On my machine, it completes in about 12.5 seconds. Mypy took 38 minutes. Pyright crashed (ran out of memory).
Charlie Marsh · @charliermarshView on X

At 15M lines, both tools show structural limits. For most teams (codebases under 500K lines), mypy wins on batch speed, and pyright wins on editor speed. Call it a tie for overall workflow.

Winner: Tie. mypy wins batch CI (the speed claim has flipped); pyright wins incremental editor. Most teams care about both.

Type Accuracy and Spec Conformance: mypy vs pyright

Pyright's correctness advantage is real and substantial, and it starts with a behavioral default most developers don't know about.

The unannotated code gap: by default, mypy skips any function that lacks type annotations, while pyright checks everything via type inference regardless of annotation coverage. On a partially-annotated codebase (which describes the vast majority of real Python projects), mypy silently provides no feedback on that code unless you add --check-untyped-defs or --strict. Pyright does it by default.

In a May 2026 error-detection test (tildalice.io, 60 intentional type errors in an 800-line data-pipeline project), pyright caught 97% (58/60) and mypy caught 57% (34/60). The 40-point gap is almost entirely explained by that default.

Typing spec conformance (python/typing conformance suite, May 2026):

Tool

Tests Passing

Conformance

pyright

135/141

95.7%

ty (beta)

95/141

67.4%

mypy

84/141

59.6%

Pyright passes 95.7% of the official typing spec tests; mypy passes 59.6%. That 36-point gap reflects implementation decisions made before the current spec was formalized, not fundamental design unsoundness. The PEP 484 reference implementation was mypy, but the spec evolved substantially beyond PEP 484, and mypy's implementation hasn't caught up in all areas.

Concrete behavioral disagreements on identical code:

Python
# Missing return statement
def func(x: int) -> int | None:
    if x > 0:
        return x
# Pyright: 0 errors (correctly infers implicit return None)
# mypy:    error: Missing return statement [return]
Python
# Variable rebinding with different type
data = ['123', '456']
data = [int(s) for s in data]
# Pyright: 0 errors (narrows data to list[int] after rebinding)
# mypy:    error: List comprehension has incompatible type List[int]; expected List[str]

Of the major Python type checkers, pyright alone fully understands `new`. A longstanding mypy bug (issue #15182) with `new` return type handling was fixed in May 2026 (post-2.1.0, pending the next release). SymPy's maintainers have been planning to migrate internal CI to pyright while keeping mypy only for checking public API compatibility with downstream libraries.

A FastAPI project benchmark (40K lines, danilchenko.dev) found pyright catching 41 errors vs mypy's 23. All 18 extra pyright errors were real issues in unannotated functions that mypy skipped.

Winner: pyright. The 97% vs 57% default detection rate is the single most important number in this comparison.

IDE and Editor Integration: mypy vs pyright

Pyright's clearest, least-contested win. It was designed from day one as a language server.

Kyle Bebak at DjangoCon US 2022 put it directly:

"I would go with Pyright. That's the one that I prefer to use. For a couple of reasons. One, Pyright is not only a type checker, it's also a language server... The other point in favor of Pyright is that the author of the library is just a fantastic programmer; he's even the author of a few Python type checking PEPs, some of which have been accepted for inclusion into Python."

Pyright ships as the engine behind Pylance, Microsoft's official Python extension for VS Code. Real-time type errors appear as you type (sub-100ms incremental LSP updates), with hover type information, go-to-definition, find-references, rename refactoring across files, and auto-imports, all without daemon setup. If your team uses VS Code, you are already running pyright via Pylance, whether you chose it or not.

mypy has no official LSP. Editor integrations (pylsp-mypy, vim-mypy) invoke mypy on save (noticeable delay on larger projects) or run dmypy for incremental checks. The experience is rougher: a VS Code user running mypy in CI is running two type models in parallel, seeing different errors in the editor than in the pipeline.

Winner: pyright. The Pylance integration makes this the least close category.

Plugin Ecosystem and Framework Support: mypy vs pyright

For teams using Django, SQLAlchemy, or Pydantic v1, mypy's plugin ecosystem is the decisive advantage. The accuracy gap here is not cosmetic.

mypy's mature plugin ecosystem:

  • django-stubs + mypy plugin: deep typing of Django models, QuerySets, forms, and admin. The plugin intercepts mypy's type inference for ORM query builders and metaclasses that produce types at runtime; static analysis cannot derive these types without framework-specific interception.
  • sqlalchemy-stubs / sqlalchemy2-stubs: ORM query builder typing for SQLAlchemy
  • Pydantic v1 plugin: model fields typed from Field() declarations

Pyright has no plugin API for framework-specific patterns: it can use standard .pyi stubs but cannot intercept ORM metaclass type inference the way mypy plugins do, producing real false positives in Django and SQLAlchemy codebases. Kyle Bebak explained the structural lock-in:

"Django-stubs bet heavily on mypy and didn't just create Python type stubs; they created a mypy plugin, which means there's syntax in there that's not compatible with standard type annotations, and other type checkers simply cannot use Django-stubs."

The workaround for pyright on Django projects is django-types, a fork of django-stubs with mypy-specific plugin syntax stripped out. It works but lags django-stubs in coverage and update cadence.

For non-ORM Python (FastAPI without SQLAlchemy, CLI tools, data science pipelines), this distinction matters far less. Pyright's native inference handles most patterns correctly without plugin assistance.

Winner: mypy (for Django/SQLAlchemy/Pydantic v1 projects). pyright (for non-ORM Python).

Configuration and CI/CD Integration: mypy vs pyright

This is less glamorous than accuracy benchmarks, but it determines which tool your CI pipeline can actually ship.

mypy configuration lives in pyproject.toml, mypy.ini, or setup.cfg. Per-module overrides let you apply different strictness levels across the codebase:

Text
[tool.mypy]
python_version = "3.12"
disallow_untyped_defs = true
check_untyped_defs = true
warn_unused_ignores = true

[[tool.mypy.overrides]]
module = "legacy.*"
ignore_errors = true

mypy installs with pip install mypy. No Node.js, no npm, no binary wrapper. u/latkde in r/Python (November 2025) described the practical friction:

"Mypy is great for CI. It's a normal Python package, so super easy to install and configure with conventional Python-oriented tooling. While Pyright is a neat LSP server and tends to run quickly, it's a NodeJS based program and cannot be installed via PyPI... I cannot declare a dependency on Pyright in a pyproject.toml file. I tend to use Pyright a lot for my personal development workflows, but it would take a lot of extra effort to use it as a quality gate."

pyright configuration lives in pyrightconfig.json or pyproject.toml, with four strictness levels: off, basic, standard (default), and strict. The gradation is more accessible for gradual adoption than mypy's binary --strict flag:

Text
{
  "typeCheckingMode": "standard",
  "reportMissingTypeStubs": "warning",
  "useLibraryCodeForTypes": true
}

The CI friction is real. Docker-based CI images must provision Node.js separately to run pyright, increasing image size and build times. Some teams work around this by running pyright only in the editor and mypy in CI, which is also the community-endorsed "run both" pattern.

Winner: mypy. pip install mypy simplicity in CI is a genuine advantage, not a trivial concern.

Pricing: mypy vs pyright

Both tools are free and open-source with no commercial tiers.

mypy Pricing

pyright Pricing

Both tools are funded through their respective backers rather than commercial licensing. The community-maintained basedpyright fork (also free) adds a stricter recommended level beyond pyright's strict and enables all rules by default, for teams who want maximum strictness without writing their own config.

Winner: Tie. Neither costs anything.

What's Coming: ty, Pyrefly, and the Rust Wave

mypy and pyright are the right frame for 2026. But the speed ceiling is shifting.

Two Rust-based type checkers are starting to change greenfield project recommendations. ty from Astral (OpenAI-backed) claims 10-100x speed over mypy on many projects and reached preview in May 2025. Pyrefly from Meta shipped v1.0 in May 2026 and checks 20M lines of Python in 30 seconds, with 92.2% typing spec conformance. pydevtools.com now recommends Pyrefly for greenfield projects.

Neither is a safe default for most teams yet. ty's 67.4% conformance means real projects will hit edge-case false positives. Pyrefly's plugin ecosystem is immature compared to mypy's.

Neil Mitchell from Meta described PyTorch's migration to Pyrefly as net-zero. The team added a few hundred type: ignore comments during the conversion and removed an equal number.

For teams where CI speed is the primary constraint (codebases above 500K lines, build times measured in minutes), ty and Pyrefly are worth evaluating now. For everyone else, the mypy vs pyright comparison is still the right one to make.

Which Type Checker Fits Your Project?

Choose pyright (or basedpyright) if you're starting a new Python project without ORM dependencies, your team uses VS Code with Pylance, or you want 97% default error detection and a built-in LSP.

Choose mypy if your project uses Django, SQLAlchemy, or Pydantic v1; you need a pure-Python CI install with no Node.js; you're adding types to a legacy codebase incrementally; or you publish a PEP 484-compatible library.

Consider running both if you want real-time IDE feedback from pyright/Pylance plus framework-accurate CI gates from mypy with plugins. James Parrott on Python Discuss made the multi-compiler case: "It's best practice in other languages to make sure your code compiles with multiple compilers; multiple type checkers is the Python equivalent."

Oscar Benjamin (SymPy maintainer) describes the split: "I use pyright as an interactive editor plugin whereas mypy is a command line tool."

The downside of running both: # type: ignore silences mypy but not pyright; # pyright: ignore silences pyright but not mypy. Teams using both accumulate dual-ignore comment debt over time. Budget for this if you go that route.

Frequently Asked Questions

Related Articles