← Back to articles

Million.js vs Bun vs uWebSockets: JavaScript Performance Tools Compared (2026)

Performance optimization in JavaScript spans different layers. Million.js optimizes React rendering. Bun replaces Node.js for faster everything. uWebSockets.js provides the fastest HTTP/WebSocket server. They solve different problems — here's when to use each.

What Each Tool Does

ToolLayerWhat It Optimizes
Million.jsFrontend (React)Virtual DOM diffing → direct DOM updates
BunRuntimeNode.js replacement (faster startup, bundling, npm)
uWebSockets.jsServerHTTP/WebSocket performance (C++ with JS bindings)

These aren't competitors — they operate at different layers of the stack.

Million.js: Faster React Rendering

Million.js is a compiler that makes React components faster by replacing React's virtual DOM diffing with direct DOM manipulation for static or predictable components.

How It Works

Million.js analyzes your React components at compile time. For components with predictable render patterns, it bypasses React's virtual DOM entirely and updates the DOM directly.

import { block } from 'million/react';

// Wrap a component with block() for Million.js optimization
const UserCard = block(({ name, avatar }) => (
  <div className="card">
    <img src={avatar} alt={name} />
    <h3>{name}</h3>
  </div>
));

When It Helps

  • Large lists rendering hundreds/thousands of items
  • Data-heavy dashboards with frequent updates
  • Components that re-render with predictable data changes
  • Performance-critical UI where every millisecond matters

When It Doesn't Help

  • Small apps (React is fast enough)
  • Complex components with heavy conditional rendering
  • Apps where rendering isn't the bottleneck (usually it isn't)

The Reality Check

Most React apps aren't slow because of virtual DOM overhead. They're slow because of unnecessary re-renders, large bundles, or bad data fetching patterns. Fix those first before reaching for Million.js.

Pricing: Free and open-source.

Bun: The Faster Node.js

Bun is a JavaScript runtime (like Node.js) built from scratch in Zig for speed. It includes a bundler, test runner, and package manager.

Performance Claims

  • Runtime: 3-6x faster than Node.js for many benchmarks
  • Package install: 10-25x faster than npm
  • Bundling: 10-100x faster than webpack
  • Test runner: 3-10x faster than Jest

When Bun Makes a Real Difference

  • Package installation. bun install is dramatically faster than npm install. This is the most universally impactful improvement.
  • Development iteration. Faster startup and hot reload speeds up the dev loop.
  • Bundling. Built-in bundler is much faster than webpack/esbuild for large projects.
  • Scripts and tooling. One-off scripts, data processing, CLI tools — Bun's startup speed matters here.

When Bun Doesn't Matter Much

  • Production API servers. Most APIs are I/O-bound (database, network), not CPU-bound. Bun's raw speed doesn't help when you're waiting for PostgreSQL.
  • Next.js/Remix apps. Framework overhead dominates runtime overhead.
  • Any app where Node.js isn't the bottleneck. (This is most apps.)

Compatibility Concerns

Bun aims for Node.js compatibility but gaps remain. Most npm packages work, but native addons and some Node.js APIs may behave differently. Test thoroughly before deploying Bun in production.

Pricing: Free and open-source.

uWebSockets.js: Maximum Server Performance

uWebSockets.js is a C++ HTTP/WebSocket server with JavaScript bindings. It's the fastest HTTP server available in the JavaScript ecosystem.

Performance

  • HTTP: 10-100x faster than Express.js
  • WebSocket: Handles millions of concurrent connections
  • Memory: Uses a fraction of the memory of Node.js HTTP

When It Makes Sense

  • High-throughput APIs. If you're handling 100K+ requests/second, uWebSockets matters.
  • WebSocket servers. Real-time applications with thousands of concurrent connections.
  • Proxy servers. High-throughput reverse proxies and load balancers.
  • Cost optimization. When server costs are significant and raw performance reduces infrastructure spend.

When It Doesn't Make Sense

  • Most web apps. Express/Fastify/Hono are fast enough for 99% of applications.
  • Apps with complex middleware. uWebSockets has a minimal API. No built-in middleware ecosystem.
  • Team productivity. The DX is worse than Express/Fastify. Developer time is usually more expensive than server time.

API Example

import { App } from 'uWebSockets.js';

App()
  .get('/api/users', (res, req) => {
    res.writeHeader('Content-Type', 'application/json');
    res.end(JSON.stringify({ users: [] }));
  })
  .ws('/ws', {
    message: (ws, message) => {
      ws.send(message); // echo
    },
  })
  .listen(3000, () => console.log('Listening on 3000'));

Pricing: Free and open-source.

Decision Framework

"My React app is slow"

  1. Profile first (React DevTools Profiler)
  2. Fix unnecessary re-renders (useMemo, React.memo)
  3. Virtualize long lists (react-window, TanStack Virtual)
  4. Code-split large bundles
  5. Then consider Million.js if rendering is still the bottleneck

"My server is slow"

  1. Profile first (where is time spent?)
  2. Optimize database queries (usually the real bottleneck)
  3. Add caching (Redis, CDN)
  4. Switch to Fastify or Hono (from Express)
  5. Then consider uWebSockets if HTTP handling is the bottleneck

"My development workflow is slow"

  1. Switch to Bun for package management (bun install)
  2. Use Bun's test runner instead of Jest
  3. Consider Bun's bundler for faster builds
  4. Run dev servers with Bun for faster startup

FAQ

Should I use all three together?

You could (Bun runtime + uWebSockets server + Million.js frontend), but you'd be over-optimizing. Use Bun for DX improvements, and only add uWebSockets or Million.js if profiling shows a specific bottleneck.

Is premature optimization still a problem?

Yes. Most performance issues are architectural (N+1 queries, missing indexes, unbounded data fetching), not runtime. Fix architecture first, optimize runtime last.

Will Bun replace Node.js?

Bun is gaining adoption but Node.js remains the standard for production. Use Bun where it helps (dev tooling, scripts) and Node.js where compatibility and stability matter (production APIs).

The Verdict

  • Million.js: Reach for it when React rendering is a proven bottleneck. Not before.
  • Bun: Use it today for bun install and dev tooling. Production use is maturing.
  • uWebSockets.js: Only when you need extreme HTTP/WebSocket performance. Most apps never will.

The most impactful performance optimization is usually fixing your database queries, not changing your runtime.

Get AI tool guides in your inbox

Weekly deep-dives on the best AI coding tools, automation platforms, and productivity software.