Library / SDK
uNetworking/uWebSockets.js avatar
uNetworking/uWebSockets.js

uWebSockets.js: a C++ server for Node.js that installs from a tag, not a registry

μWebSockets for Node.js back-ends :metal:

9,193 stars626 forksC++Apache-2.0

At a glance

What is it?
uWebSockets.js is about 10,000 lines of C++ exposed to Node.js as a native V8 addon. It is not on the NPM registry, it ships no written API tour, and its own 13x figure points at a release page rather than at a method you can rerun.
Who is it for?
Adopt it when a Node.js service needs its own HTTP and WebSocket server rather than a middleware stack, and when you are prepared to own a native build. Skip it if you need version ranges or a prose API guide, since neither comes with it.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 29 days ago.
What is it written in?
Mainly C++, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on November 14, 2026, and from our analysis. They are not legal advice.

From daily snapshots

Star history

  • uNetworking/uWebSockets.js9,193 ★ · +34
Star history
Repository2026-09-222026-11-14
uNetworking/uWebSockets.js9.2k9.2k

34 Stars in the last 53 days, measured from the daily GitHub snapshot. Compare with other projects

Editorial analysis

The install line names a tag because there is no registry entry

uWebSockets.js is not published to the NPM registry. Installation still goes through the NPM client, but the line points at a GitHub tag:

bash
npm install uNetworking/uWebSockets.js#v20.70.0

The reference is an exact tag rather than a version range, so there is no range for a caret or tilde constraint to float across, and the string has to be edited by hand whenever you want a different release. That tag is also behind the published releases. v20.71.0 shipped on 2026-09-16, v20.70.0 on 2026-09-07 and v20.69.0 on 2026-07-11, so copying the line gives you a build one release behind the newest tag. What the project cannot do for you is resolve versions, publish a package with its own dependency list, or let a lockfile carry the upgrade. Every version change is an edit to one line in your build script, and a lockfile records a commit you chose rather than a range the registry can re-resolve.

Ten thousand lines of C++ arrive as a native V8 addon

The primary language is C++, about 10,000 lines of it, and Node.js loads it as a native addon rather than as JavaScript you can read in a debugger. The layout shows how it is put together: build.c sits next to src/, .gitmodules pulls the uWebSockets library in as a submodule, and the Makefile is the build entry point. Its default target compiles one translation unit and runs the result:

makefile
default:
	$(CC) build.c
	./a.out || build.exe

The upload_host target is the part with consequences for users. It fetches a binaries branch, copies dist/*.node into the working tree, commits them under the message Manually updated host binaries, then pushes. Prebuilt binaries are therefore published by hand, not by a registry pipeline. What the project cannot do is compile on demand for an architecture nobody built. If your Node.js version and platform have no matching .node file, you are left reading build steps and supplying a local C++ toolchain, and the README does not say which platforms are covered.

The examples directory is the closest thing to an API tour

The gist promised in the README never arrives as prose. The In essence heading is followed by the licensing note, so what is left for a reader is 25 .mjs files under examples/: HelloWorld.mjs and H3lloWorld.mjs, AsyncFunction.mjs, Router.mjs, Headers.mjs, JsonPost.mjs, HttpCache.mjs, Broadcast.mjs, PubSub.mjs, Upgrade.mjs and UpgradeAsync.mjs among them, plus AutomaticPortSelection.mjs. The written reference is a generated function reference on the documentation site, while the C++ core sits in a separate upstream repository. What the project cannot do is explain its own surface in text. Your first hour with it goes on reading example source, and any call no example touches has to be found in the generated function reference or in src/.

The 13x figure is footnoted to a release rather than to a method

The README calls the server 13x faster than Fastify, and attaches that number to the v20.71.0 release page instead of describing how it was measured. The measurement work does exist in the repository: a benchmark directory, and examples/Benchmarker.mjs for driving a load test from Node.js. What is absent is everything needed to repeat the comparison, since the README names no hardware, no Node.js version, no payload shape and no Fastify version. The consequence is that 13x cannot size your capacity or defend a migration to whoever maintains the service. Run Benchmarker.mjs against your own request shapes and connection counts first, because a figure the project asserts about itself is not a number you can check.

Bun took a fork of this code and the two drifted apart

Since 2022 a fork of uWS has carried Bun to the top of benchmarks, and that fork is responsible for Bun's event loop, TLS, HTTP, QUIC, WebSockets, pub/sub and URL routing. Bun keeps its own copies under packages/bun-uws and packages/bun-usockets in its tree. What uWebSockets.js cannot do is be the implementation you get when you install Bun, which runs its own fork. The practical consequence is that a behaviour you notice in Bun's server is not something you inherit here, and running this addon under Node.js is a separate bet from the one Bun made when it diverged. If both end up in one stack, treat them as two servers that happen to share a name.

Example names point at pressure, slow peers and clean exit

Read the file list instead of the README and you get the project's own view of what is hard. RateLimit.mjs, Backpressure.mjs and SlowReceiver.mjs are there, alongside Upload.mjs, VideoStreamer.mjs with its Chunked and Sync variants, ServerSentEvents.mjs, GracefulShutdown.mjs, PeerCertificate.mjs, ProxyProtocol.mjs and ServerName.mjs. Those names are answers to clients that flood you, peers that read more slowly than you write, shutdown windows that close while requests are in flight, and TLS client identity. What the project cannot do is tell you which of them you need or how they interact, and nothing in the listing names a recommended baseline. Assembling one is design work you own, and a wrong guess costs a stalled connection that you debug with nothing but the example files.

A fork has to carry another product name under Apache 2.0

The licence is Apache License 2.0, and the README pairs it with an all rights reserved notice on intellectual property before stating the rule for derivatives: modified forks should be nothing but licensed source code, made available under another product name, with readers told to ask rather than assume. What the project cannot do is license you to ship a fork under the uWebSockets name, so a vendored or patched copy needs a rename plus a read of the Apache terms before it goes out. The repository is not archived, and its last push is dated 2026-10-16 with three releases inside the preceding four months, so this guidance is current rather than a historical note about an abandoned project.

Editorial conclusion

Adopt it when a Node.js service needs its own HTTP and WebSocket server rather than a middleware stack, and when you are prepared to own a native build. Skip it if you need version ranges or a prose API guide, since neither comes with it. Before committing, check that a .node binary exists for your Node.js version and architecture, read the example files for the features you actually need, and run examples/Benchmarker.mjs on your own payloads instead of trusting the 13x line.

Frequently asked questions

What does the WebSocket upgrade path look like in uWebSockets.js?

It ships as two example files, examples/Upgrade.mjs and examples/UpgradeAsync.mjs. The server-to-client push cases sit next to them in examples/ServerSentEvents.mjs, examples/Broadcast.mjs and examples/PubSub.mjs.

Is Socket.IO better than the WebSocket handling in uWebSockets.js?

The README claims the server is 20x faster than Socket.IO, without stating how that was measured. The repository handles the raw protocol through examples/Upgrade.mjs and examples/UpgradeAsync.mjs, with fan-out in examples/Broadcast.mjs and examples/PubSub.mjs.

uWebSockets.js vs Fastify: what is the real difference?

The README states the server is 13x faster than Fastify and footnotes that figure to the v20.71.0 release page. It gives no hardware, Node.js version or payload for the comparison.

uWebSockets.js vs Express: how do they differ?

Express is never mentioned in the README. The only comparisons the project makes are 13x faster than Fastify and 20x faster than Socket.IO, and installation takes a different shape too, since npm install uNetworking/uWebSockets.js#v20.70.0 names a GitHub tag rather than a registry version.

Official sources

  1. Issues
  2. License: Apache-2.0
  3. README
  4. Releases
  5. uNetworking/uWebSockets.js on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/unetworking-uwebsockets-js.svg)](https://hysenlabs.com/projects/unetworking-uwebsockets-js)

Star history chart for your README

markdown
[![Star history](https://hysenlabs.com/chart/unetworking-uwebsockets-js.svg)](https://hysenlabs.com/projects/unetworking-uwebsockets-js)

Was this useful?