Python type checking has a scaling problem that isn’t about throughput — it’s about latency. When you run mypy or Pyright on a 200-file project, you wait. When you save one file in your editor and the type checker kicks in, you’re waiting again, for the whole project, every time. The industry answer for years was “get a faster machine” or “use a language server for incremental feedback.” But the language server approach has limits — Pyright’s incremental mode is tied to LSP, and mypy’s daemon mode (dmypy) is fragile and underdocumented.
Astral’s ty (formerly Red-Knot) takes a different approach: build incremental analysis into the core engine from day one, using a framework called Salsa. And the evidence is in the commits.
What Salsa Actually Does for Type Checking
Salsa is a framework for incremental computation — it tracks which inputs affect which outputs, and only recomputes the outputs that actually changed. The ty codebase uses #[salsa::tracked] on methods that access .node(), which means the type checker knows, at the method level, whether a given call needs to recompute based on changes to the AST.
This isn’t just caching. A naive cache says “I already computed this, skip it.” Salsa says “I computed this given inputs X, Y, Z. If inputs X and Y haven’t changed but Z has, I can reuse the result and only recompute the part that depends on Z.”
For a type checker, this matters enormously. When you change a function signature, only the call sites that might be affected by that change need re-analysis. When you change a class definition, only the methods that depend on that class need to be re-checked. Everything else — the 90% of your codebase that doesn’t depend on what you touched — is skipped.
The ty repository at github.com/astral-sh/ty has a crates/ty_python_semantic/ crate with a #[salsa::tracked]-heavy semantic analysis layer. The AGENTS.md in the ruff repository (which houses both ruff and ty) explicitly documents this:
“Salsa incrementality (ty): Any method that accesses
.node()must be#[salsa::tracked], or it will break incrementality.”
That’s a hard constraint that the team enforces via review — and it means every semantic analysis method is designed for incremental recomputation from the start.
The Loop Header Problem
One of the recent ty commits gives a concrete window into the kind of complexity this introduces. On May 14, 2026, PR #24972 landed with the title “[ty] Bound loop-header analysis for large loops.”
Loop header analysis is a classic dataflow problem in type checkers: when you have a for loop, the type checker needs to track what types flow through the loop variable on each iteration. In a typed language this gets subtle quickly — the n-th iteration of a loop may have different type information than the (n+1)-th if the loop body narrows or widens types.
Now scale that to a loop with 10,000 iterations in the AST (generated code, test fixtures, etc.). Naively, the type checker might try to compute flow information for every iteration. For large loops this is a pathological case — O(n) analysis per iteration becomes O(n²) if you’re not careful, and the type checker hangs on a file that a human wouldn’t even look at twice.
The fix bounds the loop-header analysis — caps the iterations the analyzer will process for any single loop. The PR number is #24972, and it’s in the ty_python_semantic crate. The comment in the PR says the bound is necessary because “large loops” (not defined, but in practice anything beyond a few hundred AST nodes) would cause the analyzer to spend excessive time on generated or test code.
This is the kind of problem you only encounter when your type checker is fast enough to be used continuously. If mypy takes 30 seconds per run, you don’t notice that it handles large loops poorly — you just avoid writing 10,000-iteration for loops. But if ty runs in under a second, users will push the tool harder, and edge cases like this surface.
Why This Matters for Agent Pipelines
If you’re building multi-agent systems, you’ve probably noticed that feedback latency shapes how agents work. An agent that can check its own work in seconds behaves differently from one that waits minutes. The same is true for type checking in a development workflow.
The standard Python type-checking workflow — run mypy in CI, get feedback hours after you wrote the code — means type errors become “fix later” problems. By the time you come back to them, you’ve lost context. A type checker that runs fast enough to be part of the agent’s loop changes this. An agent that generates Python code can type-check it before returning a result, catching issues like int | str vs Union[int, str] (which ty handles differently from mypy) or missing None-aware operations.
The AGENTS.md documentation in the ruff repo mentions that ty reuses ruff_python_parser and ruff_python_ast crates — the same parser and AST definitions that power ruff’s linter. This means the parsing layer is already fast and correct, and the type checker can focus on the hard part: semantic analysis under the Salsa incremental model.
The 10–60x Number Is Real But Misleading
Every benchmark article about ty leads with “10–60x faster than mypy.” Simon Willison’s December 2025 analysis showed 10–60x on cold runs. The hot-path numbers (editor saves, incremental) are even more dramatic. But the number that matters isn’t raw speed — it’s perceived latency.
When ty runs in 200ms instead of 12 seconds, it becomes a different kind of tool. It becomes a tool you run in a loop. A tool an agent can call mid-generation. A tool that changes how you write code, because the feedback is fast enough to guide the writing rather than just audit the result.
The roadmap targets a stable 1.0 release in 2026 with “more comprehensive rule coverage” and “strict mode.” The current state (beta) means it’s not production-ready for all codebases — there are still missing type system features and occasional panics (like the overload definition panic fixed in PR #25168 on May 15). But for the specific problem of making type checking feel instant, the incremental architecture is the right foundation.
If you’re watching the Python tooling space in 2026, ty is the project to follow. Not because of the speed benchmark — because of the design bet: type checking is a fundamentally incremental problem, and building it that way from day one produces a tool that changes workflows, not just metrics.
ty is at github.com/astral-sh/ty — currently in beta, stable 1.0 targeted for 2026. The ruff repository (astral-sh/ruff) houses both ruff and ty, with shared Rust crates for parsing and AST.