diff --git a/files/en-us/web/api/closeevent/code/index.md b/files/en-us/web/api/closeevent/code/index.md
index 50f222f3e4c4d89..dd80a8d6f92fcc5 100644
--- a/files/en-us/web/api/closeevent/code/index.md
+++ b/files/en-us/web/api/closeevent/code/index.md
@@ -8,11 +8,11 @@ browser-compat: api.CloseEvent.code
{{APIRef("Websockets API")}}
-The **`code`** read-only property of the {{domxref("CloseEvent")}} interface returns a [WebSocket connection close code](https://www.rfc-editor.org/rfc/rfc6455.html#section-7.1.5) indicating the reason the server gave for closing the connection.
+The **`code`** read-only property of the {{domxref("CloseEvent")}} interface returns a [WebSocket connection close code](https://www.rfc-editor.org/rfc/rfc6455.html#section-7.1.5) indicating the reason the connection was closed.
## Value
-An integer [WebSocket connection close code](https://www.rfc-editor.org/rfc/rfc6455.html#section-7.1.5) in the range `1000` - `4999`, indicating the reason the server gave for closing the connection.
+An integer [WebSocket connection close code](https://www.rfc-editor.org/rfc/rfc6455.html#section-7.1.5) in the range `1000` - `4999`, indicating the reason the connection was closed.
diff --git a/files/en-us/web/api/closeevent/index.md b/files/en-us/web/api/closeevent/index.md
index 237ddd3b628cdbf..2800eb565cadec7 100644
--- a/files/en-us/web/api/closeevent/index.md
+++ b/files/en-us/web/api/closeevent/index.md
@@ -21,7 +21,7 @@ A `CloseEvent` is sent to clients using {{Glossary("WebSockets")}} when the conn
_This interface also inherits properties from its parent, {{domxref("Event")}}._
- {{domxref("CloseEvent.code")}} {{ReadOnlyInline}}
- - : Returns an `unsigned short` containing the close code sent by the server.
+ - : Returns an `unsigned short` containing the close code.
- {{domxref("CloseEvent.reason")}} {{ReadOnlyInline}}
- : Returns a string indicating the reason the server closed the connection. This is specific to the particular server and sub-protocol.
- {{domxref("CloseEvent.wasClean")}} {{ReadOnlyInline}}
diff --git a/files/en-us/web/api/websocket/index.md b/files/en-us/web/api/websocket/index.md
index d0c8e80d7505f93..48e06a3f1c1a89e 100644
--- a/files/en-us/web/api/websocket/index.md
+++ b/files/en-us/web/api/websocket/index.md
@@ -11,6 +11,9 @@ The `WebSocket` object provides the API for creating and managing a [WebSocket](
To construct a `WebSocket`, use the [`WebSocket()`](/en-US/docs/Web/API/WebSocket/WebSocket) constructor.
+> [!NOTE]
+> The `WebSocket` API has no way to apply [backpressure](/en-US/docs/Web/API/Streams_API/Concepts#backpressure), therefore when messages arrive faster than the application can process them, the application will either fill up the device's memory by buffering those messages, become unresponsive due to 100% CPU usage, or both. For an alternative that provides backpressure automatically, see {{domxref("WebSocketStream")}}.
+
{{InheritanceDiagram}}
## Constructor
diff --git a/files/en-us/web/api/websockets_api/index.md b/files/en-us/web/api/websockets_api/index.md
index e74539a819187ac..0afe1654332b5ad 100644
--- a/files/en-us/web/api/websockets_api/index.md
+++ b/files/en-us/web/api/websockets_api/index.md
@@ -2,12 +2,21 @@
title: The WebSocket API (WebSockets)
slug: Web/API/WebSockets_API
page-type: web-api-overview
-browser-compat: api.WebSocket
+browser-compat:
+ - api.WebSocket
+ - api.WebSocketStream
---
{{DefaultAPISidebar("WebSockets API")}}
-The **WebSocket API** is an advanced technology that makes it possible to open a two-way interactive communication session between the user's browser and a server. With this API, you can send messages to a server and receive event-driven responses without having to poll the server for a reply.
+The **WebSocket API** makes it possible to open a two-way interactive communication session between the user's browser and a server. With this API, you can send messages to a server and receive responses without having to poll the server for a reply.
+
+The WebSocket API provides two alternative mechanisms for creating and using web socket connections: the {{domxref("WebSocket")}} interface and the {{domxref("WebSocketStream")}} interface.
+
+- The `WebSocket` interface is stable and has good browser and server support. However it doesn't support [backpressure](/en-US/docs/Web/API/Streams_API/Concepts#backpressure). As a result, when messages arrive faster than the application can process them it will either fill up the device's memory by buffering those messages, become unresponsive due to 100% CPU usage, or both.
+- The `WebSocketStream` is a {{jsxref("Promise")}}-based alternative to `WebSocket`. It uses the [Streams API](/en-US/docs/Web/API/Streams_API) to handle receiving and sending messages, meaning that socket connections can take advantage of stream backpressure automatically, regulating the speed of reading or writing to avoid bottlenecks in the application. However, `WebSocketSteam` is non-standard and currently only supported in one rendering engine.
+
+Additionally, the [WebTransport API](/en-US/docs/Web/API/WebTransport_API) is expected to replace the WebSocket API for many applications. WebTransport is a versatile, low-level API that provides backpressure and many other features not supported by either `WebSocket` or `WebSocketStream`, such as unidirectional streams, out-of-order delivery, and unreliable data transmission via datagrams. WebTransport is more complex to use than WebSockets and its cross-browser support is not as wide, but it enables the implementation of sophisticated solutions. If standard WebSocket connections are a good fit for your use case and you need wide browser compatibility, you should employ the WebSockets API to get up and running quickly. However, if your application requires a non-standard custom solution, then you should use the WebTransport API.
> [!NOTE]
> While a WebSocket connection is functionally somewhat similar to standard Unix-style sockets, they are not related.
@@ -16,6 +25,8 @@ The **WebSocket API** is an advanced technology that makes it possible to open a
- [`WebSocket`](/en-US/docs/Web/API/WebSocket)
- : The primary interface for connecting to a WebSocket server and then sending and receiving data on the connection.
+- [`WebSocketStream`](/en-US/docs/Web/API/WebSocketStream) {{non-standard_inline}}
+ - : Promise-based interface for connecting to a WebSocket server; uses [streams](/en-US/docs/Web/API/Streams_API) to send and receive data on the connection.
- [`CloseEvent`](/en-US/docs/Web/API/CloseEvent)
- : The event sent by the WebSocket object when the connection closes.
- [`MessageEvent`](/en-US/docs/Web/API/MessageEvent)
@@ -28,28 +39,26 @@ The **WebSocket API** is an advanced technology that makes it possible to open a
- [Writing a WebSocket server in C#](/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_server)
- [Writing a WebSocket server in Java](/en-US/docs/Web/API/WebSockets_API/Writing_a_WebSocket_server_in_Java)
- [Writing a WebSocket server in JavaScript (Deno)](/en-US/docs/Web/API/WebSockets_API/Writing_a_WebSocket_server_in_JavaScript_Deno)
+- [Using WebSocketStream to write a client](/en-US/docs/Web/API/WebSockets_API/Using_WebSocketStream)
## Tools
- [AsyncAPI](https://www.asyncapi.com/): A specification for describing event-driven architectures based on protocols like WebSocket. You can use it to describe WebSocket-based APIs just as you would describe REST APIs with the OpenAPI specification. Learn [why you should consider using AsyncAPI with WebSocket](https://www.asyncapi.com/blog/websocket-part1) and [how to do so](https://www.asyncapi.com/blog/websocket-part2).
-- [HumbleNet](https://hacks.mozilla.org/2017/06/introducing-humblenet-a-cross-platform-networking-library-that-works-in-the-browser/): A cross-platform networking library that works in the browser. It consists of a C wrapper around WebSockets and WebRTC that abstracts away cross-browser differences, facilitating the creation of multi-user networking functionality for games and other apps.
- [µWebSockets](https://github.com/uNetworking/uWebSockets): Highly scalable WebSocket server and client implementation for [C++11](https://isocpp.org/) and [Node.js](https://nodejs.org/).
- [Socket.IO](https://socket.io/): A long polling/WebSocket based third party transfer protocol for [Node.js](https://nodejs.org/).
- [SocketCluster](https://socketcluster.io/): A pub/sub WebSocket framework for [Node.js](https://nodejs.org/) with a focus on scalability.
- [WebSocket-Node](https://github.com/theturtle32/WebSocket-Node): A WebSocket server API implementation for [Node.js](https://nodejs.org/).
- [Total.js](https://www.totaljs.com/): Web application framework for [Node.js](https://nodejs.org/en) (Example: [WebSocket chat](https://github.com/totaljs/examples/tree/master/websocket))
-- [Faye](https://www.npmjs.com/package/faye-websocket): A {{DOMxRef("WebSocket")}} (two-ways connections) and [EventSource](/en-US/docs/Web/API/EventSource) (one-way connections) for [Node.js](https://nodejs.org/) Server and Client.
- [SignalR](https://dotnet.microsoft.com/en-us/apps/aspnet/signalr): SignalR will use WebSockets under the covers when it's available, and gracefully fallback to other techniques and technologies when it isn't, while your application code stays the same.
- [Caddy](https://caddyserver.com/): A web server capable of proxying arbitrary commands (stdin/stdout) as a websocket.
- [ws](https://github.com/websockets/ws): a popular WebSocket client & server library for [Node.js](https://nodejs.org/en).
-- [jsonrpc-bidirectional](https://github.com/bigstepinc/jsonrpc-bidirectional): Asynchronous RPC which, on a single connection, may have functions exported on the server and, and the same time, on the client (client may call server, server may also call client).
- [cowboy](https://github.com/ninenines/cowboy): Cowboy is a small, fast and modern HTTP server for Erlang/OTP with WebSocket support.
- [ZeroMQ](https://zeromq.org/): ZeroMQ is embeddable networking library that carries messages across in-process, IPC, TCP, UDP, TIPC, multicast and WebSocket.
- [WebSocket King](https://websocketking.com/): A client tool to help develop, test and work with WebSocket servers.
- [PHP WebSocket Server](https://github.com/napengam/phpWebSocketServer): Server written in PHP to handle connections via websockets `wss://` or `ws://` and normal sockets over `ssl://`, `tcp://`
-- [Channels](https://channels.readthedocs.io/en/stable/index.html): Django library that adds support for WebSockets (and other protocols that require long running asynchronous connections).
-- [Channels](https://hexdocs.pm/phoenix/channels.html): Scalable real-time communication using WebSocket in Elixir Phoenix framework.
-- [LiveView](https://github.com/phoenixframework/phoenix_live_view): Real-time interactive web experiences through WebSocket in Elixir Phoenix framework.
+- [Django Channels](https://channels.readthedocs.io/en/stable/index.html): Django library that adds support for WebSockets (and other protocols that require long running asynchronous connections).
+- [(Phoenix) Channels](https://hexdocs.pm/phoenix/channels.html): Scalable real-time communication using WebSocket in Elixir Phoenix framework.
+- [Phoenix LiveView](https://github.com/phoenixframework/phoenix_live_view): Real-time interactive web experiences through WebSocket in Elixir Phoenix framework.
- [Flask-SocketIO](https://flask-socketio.readthedocs.io/en/latest/): gives Flask applications access to low latency bi-directional communications between the clients and the server.
- [Gorilla WebSocket](https://pkg.go.dev/github.com/gorilla/websocket): Gorilla WebSocket is a [Go](https://go.dev/) implementation of the WebSocket protocol.
diff --git a/files/en-us/web/api/websockets_api/using_websocketstream/index.md b/files/en-us/web/api/websockets_api/using_websocketstream/index.md
new file mode 100644
index 000000000000000..2ed559edbdbdbda
--- /dev/null
+++ b/files/en-us/web/api/websockets_api/using_websocketstream/index.md
@@ -0,0 +1,303 @@
+---
+title: Using WebSocketStream to write a client
+slug: Web/API/WebSockets_API/Using_WebSocketStream
+page-type: guide
+status:
+ - experimental
+ - non-standard
+---
+
+{{DefaultAPISidebar("WebSockets API")}}{{non-standard_header}}
+
+The {{domxref("WebSocketStream")}} API is a {{jsxref("Promise")}}-based alternative to {{domxref("WebSocket")}} for creating and using client-side WebSocket connections. `WebSocketStream` uses the [Streams API](/en-US/docs/Web/API/Streams_API) to handle receiving and sending messages, meaning that socket connections can take advantage of stream [backpressure](/en-US/docs/Web/API/Streams_API/Concepts#backpressure) automatically (no additional action required by the developer), regulating the speed of reading or writing to avoid bottlenecks in the application.
+
+This article explains how to use the {{domxref("WebSocketStream")}} API to create a WebSocket client.
+
+## Feature detection
+
+To check whether the `WebSocketStream` API is supported, you can use the following:
+
+```js
+if ("WebSocketStream" in self) {
+ // WebSocketStream is supported
+}
+```
+
+## Creating a WebSocketStream object
+
+To create a WebSocket client, you first need to create a new `WebSocketStream` instance using the {{domxref("WebSocketStream.WebSocketStream", "WebSocketStream()")}} constructor. In its simplest form, it takes the URL of the WebSocket server as an argument:
+
+```js
+const wss = new WebSocketStream("wss://example.com/wss");
+```
+
+It can also take an options object containing custom protocols and/or an {{domxref("AbortSignal")}} (see [Closing the connection](#closing_the_connection)):
+
+```js
+const controller = new AbortController();
+const chatWSS = new WebSocketStream("wss://example.com/chat", {
+ protocols: ["chat", "chatv2"],
+ signal: controller.signal,
+});
+```
+
+## Sending and receiving data
+
+The `WebSocketStream` instance has an {{domxref("WebSocketStream.opened", "opened")}} property — this returns a promise that fulfills with an object containing a {{domxref("ReadableStream")}} and a {{domxref("WritableStream")}} instance once the WebSocket connection is opened successfully:
+
+```js
+const { readable, writable } = await wss.opened;
+```
+
+Calling {{domxref("ReadableStream.getReader", "getReader()")}} and {{domxref("WritableStream.getWriter", "getWriter()")}} on these objects provides us with a {{domxref("ReadableStreamDefaultReader")}} and a {{domxref("WritableStreamDefaultWriter")}} respectively, which can be used to read from and write to the socket connection:
+
+```js
+const reader = readable.getReader();
+const writer = writable.getWriter();
+```
+
+To write data to the socket, you can use {{domxref("WritableStreamDefaultWriter.write()")}}:
+
+```js
+writer.write("My message");
+```
+
+To read data from the socket, you can continuously call {{domxref("ReadableStreamDefaultReader.read()")}} until the stream has finished, which is indicated by `done` being `true`:
+
+```js
+while (true) {
+ const { value, done } = await reader.read();
+ if (done) {
+ break;
+ }
+
+ // Process value in some way
+}
+```
+
+The browser automatically controls the rate at which the client receives and sends data by applying backpressure when needed. If data is arriving faster than the client can `read()` it, the underlying Streams API exerts backpressure on the server. In addition, `write()` operations will only proceed if it is safe to do so.
+
+## Closing the connection
+
+With `WebSocketStream`, the information previously available via the `WebSocket` {{domxref("WebSocket.close_event", "close")}} and {{domxref("WebSocket.error_event", "error")}} events is now available via the {{domxref("WebSocketStream.closed", "closed")}} property — this returns a promise that fulfills with an object containing the closing code (see the full list of [`CloseEvent` status codes](/en-US/docs/Web/API/CloseEvent/code#value)) and reason indicating why the server closed the connection:
+
+```js
+const { code, reason } = await wss.closed;
+```
+
+As mentioned earlier, the WebSocket connection can be closed using an {{domxref("AbortController")}}. The necessary {{domxref("AbortSignal")}} is passed to the `WebSocketStream` constructor during creation, and {{domxref("AbortController.abort()")}} can then be called when required:
+
+```js
+const controller = new AbortController();
+const wss = new WebSocketStream("wss://example.com/wss", {
+ signal: controller.signal,
+});
+
+// some time later
+
+controller.abort();
+```
+
+Alternatively you can use the {{domxref("WebSocketStream.close()")}} method to close a connection. This is mainly used if you wish to specify a custom code and/or reason:
+
+```js
+wss.close({
+ code: 4000,
+ reason: "Night draws to a close",
+});
+```
+
+> [!NOTE]
+> Depending on the server setup and status code you use, the server may choose to ignore a custom code in favor of a valid code that is correct for the closing reason.
+
+## A complete sample client
+
+To demonstrate basic usage of `WebSocketStream`, we've created a sample client. You can see the [full listing](#full_listing) at the bottom of the article, and follow along with the explanation below.
+
+> [!NOTE]
+> To get the example working, you'll also need a server component. We wrote our client to work along with the Deno server explained in [Writing a WebSocket server in JavaScript (Deno)](/en-US/docs/Web/API/WebSockets_API/Writing_a_WebSocket_server_in_JavaScript_Deno), but any compatible server will do.
+
+The HTML for the demo is as follows. It includes informational [`
`](/en-US/docs/Web/HTML/Element/Heading_Elements) and {{htmlelement("p")}} elements, a {{htmlelement("button")}} to close the WebSocket connection that is initially disabled, and a {{htmlelement("div")}} for us to write output messages into.
+
+```html
+
WebSocketStream Test
+
Sends a ping every five seconds
+
+
+```
+
+Now on to the JavaScript. First we grab references to the output `