Skip to content
Latchkey

Oxlint vs ESLint: Why Large Repos Run Both

Oxlint runs 50 to 100 times faster than ESLint and ships more than 865 rules. It is still not a full replacement, because JS plugin support is alpha. The pattern that actually works today is running both.

Oxlint is a linter for JavaScript and TypeScript built on the Oxc compiler stack in Rust. Its headline claim is that it runs 50 to 100 times faster than ESLint, and unlike most performance claims in this space it is not marginal: it is the difference between a lint step you wait for and one you do not notice. Elastic Kibana, Sentry, and Cloudflare run it in production.

The question everyone actually asks is whether it replaces ESLint. As of 2026 the honest answer is not yet, and the reason is narrow and specific: oxlint supports native plugins and JS plugins compatible with the ESLint plugin ecosystem, but the JS plugin support is still alpha. If your config depends on a custom in-house rule or a niche community plugin, that is the thing that will stop a clean migration, not rule count and not speed.

So the useful comparison is not "which one wins". It is which parts of your lint config can move today, what running both costs you, and what has to be true before a full migration makes sense. ESLint v10 with flat config is the reference point throughout.

Oxlint vs ESLint at a glance

OxlintESLint
ImplementationRust, on the Oxc compiler stackJavaScript
Speed50-100x faster (vendor benchmark)Baseline
Rules865+ including core, TypeScript, React, Jest, VitestCore plus the full plugin ecosystem
Custom JS pluginsAlphaMature, the ecosystem standard
Native pluginsYesNot applicable
Type-aware lintingYes, via tsgo (TypeScript 7)Yes, via typescript-eslint
Config formatOwn config, ESLint-likeFlat config (eslint.config.js) in v9 and v10
AutofixYes (--fix)Yes (--fix)
Editor integrationAvailableUniversal
Drop-in replacementNot yetn/a

What 50-100x actually buys you in CI

Speed multipliers are easy to dismiss until you convert them to the thing you actually pay for, which is wall-clock time on every push and every pull request.

ESLint lint stepOxlint at 50xOxlint at 100x
10 seconds0.2 s0.1 s
60 seconds1.2 s0.6 s
3 minutes3.6 s1.8 s
8 minutes (large monorepo)9.6 s4.8 s

Rule coverage: 865+ rules, and the gap that matters

Oxlint ports ESLint core rules plus TypeScript rules and popular plugin rule sets including React, Jest, and Vitest. For a mainstream config that is most of what a typical eslint.config.js enables.

  • What ports cleanly: core correctness rules, TypeScript rules, React hooks and JSX rules, and the common test-framework plugins.
  • What does not: your own in-house rules, and smaller community plugins nobody has ported.
  • Rule *names* mostly match ESLint, so disable comments and config intent carry over more easily than a rewrite would suggest.

Type-aware linting is the newest and biggest change

Type-aware rules are the ones that need the type checker rather than just the syntax tree: floating promises, unsafe any propagation, misused promises. Historically these were ESLint-only via typescript-eslint, and they were also the slowest rules in any config because they require a full type-check.

  • Oxlint now supports type-aware linting by integrating with the TypeScript Go port (tsgo, TypeScript 7), enabling checks such as floating promise detection.
  • This removes what used to be the strongest technical reason a TypeScript codebase could not consider oxlint at all.
  • It is also the area moving fastest, so verify current coverage against the rules you actually depend on rather than assuming parity.

The real blocker: custom plugins are alpha

If you maintain in-house rules, this is the whole decision. Oxlint supports JS plugins compatible with the ESLint plugin ecosystem, but that support is documented as alpha. Alpha is fine for a lint experiment and not fine for the gate that blocks your merges.

  • A repo with no custom rules and mainstream plugins can often migrate today.
  • A repo with in-house rules that encode architectural constraints should keep ESLint for those rules specifically.
  • Native (Rust) plugins are stable but mean writing Rust, which is a different proposition from maintaining a JS rule.

The pattern large repos actually use: both

Rather than choosing, run oxlint as a fast pre-filter and ESLint for the rules oxlint cannot yet cover. You get the fast feedback loop where it matters and keep full rule coverage where you need it.

Running both, fast pass first
# package.json scripts
{
  "scripts": {
    "lint:fast": "oxlint",
    "lint:full": "eslint .",
    "lint": "oxlint && eslint ."
  }
}

# .github/workflows/ci.yml
jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with: { node-version: 22, cache: npm }
      - run: npm ci
      # Fails in about a second on the 865 rules oxlint covers,
      # so the slow full pass only runs on code that already passes.
      - run: npx oxlint
      - run: npx eslint .

When a full migration makes sense

  1. Inventory your ESLint plugins and custom rules, and check each against the oxlint rule list.
  2. If nothing custom appears, run oxlint alongside ESLint in CI for a couple of weeks and diff the findings.
  3. Investigate every disagreement. Rules with the same name can differ at the edges, and those edges are where a silent behaviour change hides.
  4. Move the fast pass into a pre-commit hook once you trust it, so lint failures stop reaching CI at all.
  5. Retire ESLint only when the diff is empty and nothing in your config depends on alpha JS plugin support.

The switching cost is mostly in the parts nobody lists

  • Assertions and mocks usually port mechanically when the target implements a compatible API; custom transformers and framework plugins do not.
  • Snapshot formats differ between runners, so plan to regenerate and review rather than port.
  • Run both suites in parallel in CI for a period and diff the results. A migration that changes which tests fail is not a migration, it is a regression you have not found yet.
  • Coverage numbers move on a runner change even when the tests do not, because instrumentation differs. Re-baseline any coverage gate deliberately.

The verdict

Do not frame this as a replacement decision yet. Oxlint is dramatically faster, covers 865+ rules including TypeScript, React, and the common test plugins, and now does type-aware linting via tsgo. That is enough to be genuinely useful today.

It is not enough to retire ESLint in a repo with in-house rules, because JS plugin support is still alpha and that is exactly the part your custom rules depend on.

Run both, oxlint first. You get sub-second feedback on the vast majority of violations and keep full coverage from ESLint, and the migration path stays open for whenever plugin support stabilises. That is the configuration most large adopters are actually running.

Frequently asked questions

Is oxlint a drop-in replacement for ESLint?
Not yet. It covers 865+ rules and rule names largely match ESLint, so mainstream configs port well. The blocker is that JS plugin support - what custom and niche community rules rely on - is still alpha. Repos with no in-house rules can often migrate; repos with them should keep ESLint for those rules.
How much faster is oxlint than ESLint?
The published benchmark is 50 to 100 times faster. In practice that turns a 60-second lint step into roughly one second, and an eight-minute monorepo lint into under ten seconds. The bigger effect is qualitative: a sub-second lint can run on every save and as a pre-commit hook, so failures stop reaching CI.
Does oxlint support type-aware linting?
Yes, through integration with the TypeScript Go port (tsgo, TypeScript 7), which enables checks like floating promise detection. This is recent and moving quickly, so verify coverage of the specific type-aware rules you rely on rather than assuming full parity with typescript-eslint.
How many rules does oxlint have?
More than 865, spanning ESLint core rules, TypeScript rules, and popular plugin rule sets including React, Jest, and Vitest.
Can I run oxlint and ESLint together?
Yes, and it is the recommended pattern. Run oxlint first so the majority of violations surface in about a second, then run eslint . for the rules oxlint does not cover. Failure latency improves with no loss of coverage.
Who uses oxlint in production?
Elastic Kibana, Sentry, and Cloudflare are named adopters. Notably these are large codebases, which is the case where the speed difference compounds most and where a full ESLint pass is most painful.
Does oxlint support autofix?
Yes, via oxlint --fix, the same shape as eslint --fix. Because it is so much faster, autofix on save is practical in a way a slow ESLint pass often is not.
Will my ESLint disable comments still work?
Largely, because oxlint deliberately matches ESLint rule names. That said, rules sharing a name can differ at the edges, so run both in parallel for a period and diff the findings before you retire anything.

Related guides

References

Run this faster and cheaper on Latchkey managed runners - self-healing included. Start free → 30-day trial · No credit card