You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
There is a new category of server frameworks called runtime-agnostic or edge-first. They are typically designed for different runtimes (Cloudflare Workers, Fastly, Vercel, Bun, Deno, etc), and they use web-standards fetch API interfaces, like Request and Response, to represent incoming requests and outgoing responses, instead of node-specific HTTP APIs.
Node doesn't support fetch APIs for the request/response lifecycle. So if you wanted to use one of these newer frameworks, you would need to use an adapter (1, 2, 3) to translate between the Request/Response and http.IncomingMessage/http.ServerResponse interfaces. This works okay, but it's not an ideal experience because the translation adds extra overhead and you miss out on any of the performance benefits you might gain from these newer frameworks and runtimes.
uws-server solves these problems by natively supporting fetch APIs for the request/response lifecycle and using uWebSockets for the networking layer under the hood, bypassing node's networking stack completely. This gives you next-gen performance and modern tooling directly in node.
You can think of it like a high-performance general-purpose server that supports using any web-standards based framework on top of it. If you're familiar with Python, this would be equivalent to the lower-level Uvicorn layer, which powers higher-level frameworks like FastAPI.
Is this a drop-in replacement for express, etc?
No, this is a custom built lower-level server implementation that uses a high-performance networking layer called uWebSockets to bypass the node networking stack completely.
It's meant to be used in conjunction with higher-level, web-standards based routing/middleware frameworks like Hono, Elysia, H3, etc
It's been verified to work so far with Hono, Elysia, and H3, which also have dedicated adapter entrypoints for the serveStatic middleware and conninfo helper
Other runtimes?
It's technically possible to support other runtimes, but uWebSockets only provides bindings for node currently
Which entrypoint should I use?
The main entrypoint is framework-neutral. The serve and Server functions work with any framework, and serveStatic and conninfo work directly with web standard Request objects
import{serve,serveStatic}from'uws-server';
Framework users should import from the adapter entrypoints, which export the same server functions plus a ServeStatic subclass and conninfo bound to that framework's context shape
Note: If you mount the generic serveStatic middleware inside a framework by mistake, it throws an unknown request method error. That's the signal to switch to the adapter import
Support for other frameworks can be added with a small subclass, see the readme for details
Can I pass my app instance directly to serve?
Yes. Any object that exposes a fetch method works, the server unwraps it automatically
serve({fetch: app});
Why is it fast?
uWebSockets handles all the networking, Node's HTTP stack is bypassed entirely. With the globals option (default true), the built-in Request and Response globals are replaced with lightweight versions that create expensive allocations (headers, streams, abort controllers) lazily on access. Most responses never need to build the full Response object at all, and the raw body is written directly to the socket, with backpressure handled at the uWS layer
Based on the benchmarks, this achieves ~90% the throughput of vanilla uWebSockets, while keeping full framework routing and middleware support
What does the static middleware support?
Compression (br, gzip, zstd, deflate), range requests (open ended and suffix forms, proper 206/416 responses), cache headers (last-modified, cache-control, immutable), and an in-memory LRU cache for small files
Cache keys include file mtime and size, so changed files are never served stale. Cache hits skip the file system entirely and typically respond in under a millisecond
What happens if a response is sent without reading the request body?
Small unread remainders (up to discardMax, default 32KB) are drained so the keep-alive connection stays safe to reuse. Larger or unknown remainders get a connection: close response instead, so clients never reuse a connection that is still mid-request
How does graceful shutdown work?
On shutdown signals (SIGINT, SIGTERM by default) the server closes the listen socket, runs any registered shutdown handlers in order, waits up to timeout ms for in-flight requests to drain (force-closing stragglers after that), then closes any remaining idle keep-alive connections so the process can exit cleanly
Websocket upgrade support?
There isn't a direct API for websocket upgrade (yet), but the underlying TemplatedApp instance is exposed on the server. So you can add a websocket upgrade handler directly (after initialization):
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
What is uws-server?
There is a new category of server frameworks called runtime-agnostic or edge-first. They are typically designed for different runtimes (Cloudflare Workers, Fastly, Vercel, Bun, Deno, etc), and they use web-standards fetch API interfaces, like
RequestandResponse, to represent incoming requests and outgoing responses, instead of node-specific HTTP APIs.Node doesn't support fetch APIs for the request/response lifecycle. So if you wanted to use one of these newer frameworks, you would need to use an adapter (1, 2, 3) to translate between the
Request/Responseandhttp.IncomingMessage/http.ServerResponseinterfaces. This works okay, but it's not an ideal experience because the translation adds extra overhead and you miss out on any of the performance benefits you might gain from these newer frameworks and runtimes.uws-server solves these problems by natively supporting fetch APIs for the request/response lifecycle and using uWebSockets for the networking layer under the hood, bypassing node's networking stack completely. This gives you next-gen performance and modern tooling directly in node.
You can think of it like a high-performance general-purpose server that supports using any web-standards based framework on top of it. If you're familiar with Python, this would be equivalent to the lower-level Uvicorn layer, which powers higher-level frameworks like FastAPI.
Is this a drop-in replacement for express, etc?
No, this is a custom built lower-level server implementation that uses a high-performance networking layer called uWebSockets to bypass the node networking stack completely.
It's meant to be used in conjunction with higher-level, web-standards based routing/middleware frameworks like Hono, Elysia, H3, etc
Which frameworks does it work with?
uws-server will work with any framework that supports web-standards fetch API interfaces. In particular, it needs to expose a fetch function that accepts a Request object and returns a Response object.
It's been verified to work so far with Hono, Elysia, and H3, which also have dedicated adapter entrypoints for the
serveStaticmiddleware andconninfohelperOther runtimes?
It's technically possible to support other runtimes, but uWebSockets only provides bindings for node currently
Which entrypoint should I use?
The main entrypoint is framework-neutral. The
serveandServerfunctions work with any framework, andserveStaticandconninfowork directly with web standardRequestobjectsFramework users should import from the adapter entrypoints, which export the same server functions plus a
ServeStaticsubclass andconninfobound to that framework's context shapeNote: If you mount the generic
serveStaticmiddleware inside a framework by mistake, it throws an unknown request method error. That's the signal to switch to the adapter importSupport for other frameworks can be added with a small subclass, see the readme for details
Can I pass my app instance directly to serve?
Yes. Any object that exposes a
fetchmethod works, the server unwraps it automaticallyWhy is it fast?
uWebSockets handles all the networking, Node's HTTP stack is bypassed entirely. With the
globalsoption (default true), the built-inRequestandResponseglobals are replaced with lightweight versions that create expensive allocations (headers, streams, abort controllers) lazily on access. Most responses never need to build the fullResponseobject at all, and the raw body is written directly to the socket, with backpressure handled at the uWS layerBased on the benchmarks, this achieves ~90% the throughput of vanilla uWebSockets, while keeping full framework routing and middleware support
What does the static middleware support?
Compression (
br,gzip,zstd,deflate), range requests (open ended and suffix forms, proper 206/416 responses), cache headers (last-modified, cache-control, immutable), and an in-memory LRU cache for small filesCache keys include file
mtimeandsize, so changed files are never served stale. Cache hits skip the file system entirely and typically respond in under a millisecondWhat happens if a response is sent without reading the request body?
Small unread remainders (up to
discardMax, default 32KB) are drained so the keep-alive connection stays safe to reuse. Larger or unknown remainders get aconnection: closeresponse instead, so clients never reuse a connection that is still mid-requestHow does graceful shutdown work?
On shutdown signals (
SIGINT,SIGTERMby default) the server closes the listen socket, runs any registered shutdown handlers in order, waits up totimeoutms for in-flight requests to drain (force-closing stragglers after that), then closes any remaining idle keep-alive connections so the process can exit cleanlyWebsocket upgrade support?
There isn't a direct API for websocket upgrade (yet), but the underlying
TemplatedAppinstance is exposed on the server. So you can add a websocket upgrade handler directly (after initialization):All reactions