Skip to main content

Oxlint vs ESLint: Rust-Powered Linting Performance 2026

·PkgPulse Team

TL;DR

Oxlint is 50-100x faster than ESLint and ready for production — but as a complement, not a replacement. It runs first as a fast pass catching common errors (500+ rules), then ESLint handles TypeScript-aware rules and plugins that Oxlint doesn't support yet. The Vercel team runs both in CI: oxlint in < 1 second, ESLint in parallel only for the rules oxlint misses. For solo TypeScript projects, oxlint + ESLint is the performance-optimal stack in 2026.

Key Takeaways

  • Oxlint: ~400K downloads/week, written in Rust (via oxc), 500+ rules, ~1s on large codebases
  • ESLint: 30M downloads/week, ecosystem standard, TypeScript-aware rules, full plugin system
  • Speed: Oxlint is 50-100x faster than ESLint on the same rules
  • Coverage: Oxlint covers ~50-60% of what most projects need from ESLint
  • Strategy: Run oxlint as fast pre-check, ESLint for type-aware rules only
  • No plugins: Oxlint doesn't support custom plugins (yet) — ecosystem rules (Tailwind, a11y) still need ESLint

Downloads

PackageWeekly DownloadsTrend
eslint~30M→ Stable
oxlint~400K↑ Fast growing
@biomejs/biome~1.2M↑ Growing

Oxlint: Setup and Rules

npm install --save-dev oxlint
// package.json — run oxlint first:
{
  "scripts": {
    "lint": "oxlint --deny-warnings && eslint --max-warnings 0 ."
  }
}
// oxlintrc.json (optional — oxlint has good defaults):
{
  "$schema": "./node_modules/oxlint/configuration_schema.json",
  "rules": {
    // Correctness (errors):
    "no-unused-vars": "error",
    "no-undef": "error",
    "eqeqeq": "error",
    "no-debugger": "error",
    
    // React rules (built-in, no plugin needed):
    "react/jsx-key": "error",
    "react/no-danger": "warn",
    "react-hooks/rules-of-hooks": "error",
    "react-hooks/exhaustive-deps": "warn",
    
    // TypeScript rules (built-in):
    "typescript/no-explicit-any": "warn",
    "typescript/no-unused-vars": "error",
    
    // Unicorn-style rules (subset):
    "unicorn/prefer-array-flat-map": "warn",
    "unicorn/prefer-string-trim-start-end": "warn"
  },
  "plugins": ["react", "react-hooks", "typescript", "unicorn"],
  "env": {
    "browser": true,
    "node": true,
    "es2022": true
  }
}

Speed Benchmark

Next.js project: 1200 TypeScript files, 85K lines

ESLint (with typescript-eslint, react, import):
  Cold run:  ~45s
  Warm run:  ~38s

Oxlint (equivalent rules):
  Cold run:  0.4s
  Warm run:  0.4s  (Rust, no JS startup)

ESLint (minimal — type-aware rules only, no react/import):
  Cold run:  12s
  Warm run:  8s

Optimal combo:
  oxlint:           0.4s  (catches 60% of issues instantly)
  eslint-minimal:   8s    (only type-aware rules in parallel)
  Total effective:  8s (parallel) vs 38s ESLint-only

What Oxlint Covers vs What It Doesn't

✅ Oxlint has built-in:
  - Core JavaScript rules (no-unused-vars, eqeqeq, etc.)
  - React + React Hooks rules
  - TypeScript basic rules
  - Subset of unicorn rules
  - Import/export validation (basic)
  - Performance anti-patterns

❌ Still needs ESLint:
  - Type-aware TypeScript rules (@typescript-eslint with type-checking)
    e.g., @typescript-eslint/await-thenable
          @typescript-eslint/no-floating-promises
          @typescript-eslint/no-misused-promises
  - eslint-plugin-tailwindcss (class sorting)
  - eslint-plugin-jsx-a11y (accessibility)
  - Custom organization rules
  - eslint-plugin-import (advanced cycle detection)
  - Security rules

Optimal ESLint Config (Paired with Oxlint)

When using oxlint as the primary linter, reduce ESLint to only what it does uniquely well:

// eslint.config.js — minimal, only type-aware rules + plugins:
import tsPlugin from '@typescript-eslint/eslint-plugin';
import tsParser from '@typescript-eslint/parser';
import tailwindPlugin from 'eslint-plugin-tailwindcss';
import a11y from 'eslint-plugin-jsx-a11y';
import prettierConfig from 'eslint-config-prettier';

export default [
  {
    files: ['**/*.{ts,tsx}'],
    languageOptions: {
      parser: tsParser,
      parserOptions: {
        project: './tsconfig.json',  // Required for type-aware rules
        tsconfigRootDir: import.meta.dirname,
      },
    },
    plugins: { '@typescript-eslint': tsPlugin },
    rules: {
      // Only type-aware rules that oxlint can't do:
      '@typescript-eslint/await-thenable': 'error',
      '@typescript-eslint/no-floating-promises': 'error',
      '@typescript-eslint/no-misused-promises': 'error',
      '@typescript-eslint/no-unnecessary-type-assertion': 'warn',
      '@typescript-eslint/strict-boolean-expressions': 'warn',
    },
  },
  {
    plugins: {
      tailwindcss: tailwindPlugin,
      'jsx-a11y': a11y,
    },
    rules: {
      'tailwindcss/classnames-order': 'warn',
      ...a11y.configs.recommended.rules,
    },
  },
  prettierConfig,
];

Pre-commit Hook (husky + lint-staged)

// .lintstagedrc.json:
{
  "*.{ts,tsx,js,jsx}": [
    "oxlint",           // Fast: runs in ~200ms on changed files
    "eslint --fix"      // Slower: only type-aware + plugin rules
  ],
  "*.{ts,tsx,js,jsx,json,md,css}": ["prettier --write"]
}

Comparison Table

OxlintESLintBiome
Speed50-100x fasterBaseline25x faster
Rule count500+10,000+ (w/ plugins)300+
Plugin system❌ (planned)✅ Full ecosystem
Type-aware rules
TypeScript formattingvia Prettier
Tailwind sorting✅ (plugin)
Maturity2023/growing2013/mature2023/growing

Decision Guide

Use Oxlint if:
  → CI lint times are painful (>30s on ESLint)
  → Running oxlint as a first-pass alongside ESLint
  → New project comfortable with cutting-edge tools

Keep ESLint-only if:
  → Need full plugin ecosystem without hybrid complexity
  → Team unfamiliar with multi-linter setup
  → Custom rules or plugins are required

Optimal stack for TypeScript projects:
  oxlint + minimal ESLint (type-aware) + Prettier
  → Fast feedback: oxlint in <1s
  → Comprehensive: ESLint for type-aware rules
  → Formatting: Prettier (or Biome if no Tailwind sorting needed)

Compare oxlint and ESLint package health on PkgPulse.

Comments

Stay Updated

Get the latest package insights, npm trends, and tooling tips delivered to your inbox.