The Ultimate WebSocket server. ws-compatible server, based on uWebSockets.
npm install ultimate-wsThe Ultimate WebSocket server. Ultimate WS is an extremely fast, drop-in replacement for ws module, with support for Ultimate Express http upgrades. It uses uWebSockets.js under the hood.
It's useful when:
- You want same API as ws module, but the speed of uWebSockets.js
- You want to convert your Express app with ws to use Ultimate Express instead



1.
``bash`
npm install ultimate-wsws
2. Replace with ultimate-ws in your code
3. Check compatibility and differences below
Echo test using artillery (duration: 20, arrivalRate: 10000):
| Module | Send rate | Mean Session length | Median Session length |
|-------------------|---------------|---------------------|-----------------------|
| ws | 2709/sec | 2535ms | 127ms |ultimate-ws
| | 10046/sec | 45ms | 12ms |
Since you don't create http server for ws or express, you can't really use server.on("upgrade", ...) to upgrade to Ultimate WS. Instead, you can pass Ultimate Express or uWS app to WebSocketServer as option. So instead of doing this:`js
const http = require("http");
const express = require("express");
const ws = require("ws");
const app = express();
const wsServer = new ws.WebSocketServer({ noServer: true });
app.get("/", (_, res) => res.send("Hello, world!"));
const server = http.createServer(app);
server.on("upgrade", (request, socket, head) => {
const { pathname } = url.parse(request.url);
if(pathname !== "/wspath") return request.socket.destroy();
wsServer.handleUpgrade(request, socket, head, (ws) => {
wsServer.emit("connection", ws, request);
});
});
server.listen(3000);
``
You need to do this:js
const express = require("ultimate-express");
const app = express();
const { WebSocketServer } = require("ultimate-ws");
app.get("/", (_, res) => res.send("Hello, world!"));
const wsServer = new WebSocketServer({ server: app, path: "/wspath" }); // path is optional
// your usual ws server code ...
app.listen(3000);
`
Ultimate Express is fully compatible, much faster express implementation.
If you want to use Ultimate WS without any existing http server, you can do this:
`js
const { WebSocketServer } = require("ultimate-ws");
const wsServer = new WebSocketServer({ port: 3000 });
// your usual ws server code ...`
wsServer.on("connection", (ws) => {
ws.on("message", (message) => {
ws.send(message);
});
});
You can also pass existing uWS server to WebSocketServer:`js
const { WebSocketServer } = require("ultimate-ws");
const uws = require("uWebSockets.js");
const server = uws.App();
const wsServer = new WebSocketServer({ server: server });
// your usual ws server code ...
server.listen(3000);
`
Ultimate WS supports HTTPS. You can pass uwsOptions to WebSocketServer to configure it:`js
const { WebSocketServer } = require("ultimate-ws");
const wsServer = new WebSocketServer({
port: 3000,
uwsOptions: {
// https://unetworking.github.io/uWebSockets.js/generated/interfaces/AppOptions.html
key_file_name: "path/to/key.pem",
cert_file_name: "path/to/cert.pem",
}
});
`
Instead of this:
`js
const http = require("http");
const express = require("express");
const ws = require("ws");
const app = express();
const wsServer = new ws.WebSocketServer({ noServer: true, path: "/wspath" });
app.get("/", (_, res) => res.send("Hello, world!"));
const server = http.createServer(app);
server.on("upgrade", async (request, socket, head) => {
// your auth logic
const user = await getUserFromDatabase(request.headers['authorization']);
if(!user) return socket.destroy();
wsServer.handleUpgrade(request, socket, head, (ws) => {
ws.user = user;
wsServer.emit("connection", ws, request);
});
});
server.listen(3000);
`
You should do this:
`js
const { WebSocketServer } = require("ultimate-ws");
const express = require("ultimate-express");
const app = express();
const wsServer = new WebSocketServer({
server: app,
path: "/wspath",
handleUpgrade: async (request) => {
// your auth logic
const user = await getUserFromDatabase(request.headers['authorization']);
if(!user) {
// request has req and res propertiesuws.HttpRequest
// which are instances of and uws.HttpResponse
request.res.cork(() => {
request.res.writeStatus("401 Unauthorized");
request.res.end();
});
return false;
}
return (ws, request) => {
ws.user = user;
wsServer.emit("connection", ws, request);
}
}
});
app.get("/", (_, res) => res.send("Hello, world!"));
app.listen(3000);
`
- if handleUpgrade returns a function, it will be called with the new WebSocket instance and original request. "connection" will not be emitted automatically.false
- if it returns , the connection will not be upgraded. It's your responsibility to destroy the socket.handleUpgrade: undefined
- if it returns nothing or anything else, the connection will be handled as usual, and "connection" event will be emitted.
- By default (), the connection will be handled as usual, and "connection" event will be emitted.
Compatibility
All commonly used ws features are supported. Almost all ws servers should work, as it's built with maximum compatibility in mind.
Please refer to ws module documentation for API reference.
Below is the list of supported features and their compatibility:
โ
- Full support (all features and options are supported)
๐ง - Partial support (some features are not supported)
โ - Not supported
#### WebSocket
- โ
WebSocket
- โ
WebSocket.Server
- โ
WebSocket.WebSocket
- โ
WebSocket.WebSocketServer
- โ
WebSocket.CONNECTING
- โ
WebSocket.OPEN
- โ
WebSocket.CLOSING
- โ
WebSocket.CLOSED
- โ
WebSocket.createWebSocketStream
#### Server options
ws options:
- โ
autoPong (maps to uWS sendPingsAutomatically, default true)false
- โ
allowSynchronousEvents (may lower performance when , default true)true
- โ
clientTracking
- โ
handleProtocols
- โ
host
- โ
maxPayload (default 100mb)
- โ
path
- ๐ง perMessageDeflate - pass for DEDICATED_COMPRESSOR_4KB | DEDICATED_DECOMPRESSOR or your own CompressOptions number. Options are not supported and if this is an object it will be treated as true.
- โ
port
- โ
server
- โ
verifyClient
- โ
WebSocket
- โ
callback
- โ noServer - see examples above for alternatives
- โ skipUTF8Validation - uWS always validates UTF-8 when message is a string
- โ backlog
uWS options (additional options that ws doesn't have):
- โ
maxBackpressure (default maxPayload)false
- โ
idleTimeout (default 120)
- โ
maxLifetime (default 0)
- โ
closeOnBackpressureLimit (default )
#### Server events
- โ
close
- โ
connection
- โ
headers
- โ
listening
- โ
error - ยตWS never throws errors
- โ
wsClientError - ยตWS never throws errors
#### Server properties
- โ
server.address()
- โ
server.clients
- โ
server.close(callback)
- โ
server.shouldHandle(request)
- โ server.handleUpgrade(request, socket, head, callback) - see examples above for alternatives
This category only describes server clients. Client-side (new ws.WebSocket()) just uses original ws` module, and therefore supports everything.
#### Client events
- โ
close
- โ
message
- โ
ping
- โ
pong
- โ
dropped - this event only exists in Ultimate WS for handling dropped messages
- โ
drain - this event only exists in Ultimate WS for handling backpressure draining
- โ
error - ยตWS never throws errors
#### Client properties
- โ
client.addEventListener(type, listener, options)
- โ
client.binaryType
- โ
client.bufferedAmount
- โ
client.close(code, reason)
- โ
client.isPaused
- โ
client.extensions
- โ
client.onclose
- โ
client.onerror
- โ
client.onmessage
- โ
client.onopen
- โ
client.pause()
- ๐ง client.ping()
- โ client.pong(data, mask, callback) - pongs are handled automatically, method does nothing
- โ
client.protocol
- โ
client.resume()
- โ
client.readyState
- โ
client.removeEventListener(type, listener)
- ๐ง client.send(data, options, callback) - returns 1 for success, 2 for dropped due to backpressure limit, 0 for built up backpressure that will drain over time. Callback will only get error if it returns 2.
- - โ
options.binary
- - โ
options.compress
- - โ options.fin
- - โ options.mask
- โ
client.terminate()