# WebSocket

The WebSocket API of Azion Runtime lets a function act as a WebSocket server or as a WebSocket client, and carry bidirectional traffic to backend services. The function itself accepts or opens the connection, which separates this API from [WebSocket Proxy](/en/documentation/platform/applications/websocket/), where an application only carries the connection to a WebSocket server at your origin. Use the WebSocket API for real-time workloads such as chat, multiplayer games, telemetry dashboards, and AI inference streams.

> **Note**
>
> Under `azion dev`, `upgradeWebSocket` and `WebSocket` are not defined. A call to `upgradeWebSocket()` throws `ReferenceError: upgradeWebSocket is not defined`, and `new WebSocket()` throws `TypeError: WebSocket is not a constructor`. Deployed, both globals are defined as functions.

---

## Availability

The WebSocket API is available to customers with Business, Enterprise, or Mission-Critical Support, and to customers with a Reserved Capacity or Saving Plan contract. To request access, contact [Technical Support](/en/documentation/support/).

---

## Server and client modes

A deployed function reaches both modes through two globals:

| Global                      | Mode   | Description                                                                                                                                                                                                      |
| --------------------------- | ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `upgradeWebSocket(request)` | Server | Accepts the WebSocket upgrade of an incoming request. Returns an object with `response` and `socket`: return `response` from the handler to complete the upgrade, and use `socket` to send and receive messages. |
| `WebSocket(url)`            | Client | The standard `WebSocket` constructor. Opens an outbound WebSocket connection from the function to `url`.                                                                                                         |

`upgradeWebSocket()` accepts only a request whose `upgrade` header contains `websocket`. Called with any other request, it throws `TypeError: Invalid Header: 'upgrade' header must contain 'websocket'`, so check the header before the call, as the example below does.

Azion Runtime also provides helpers that broadcast a message to every connected client, so one function can fan out a message to all of its connections.

---

## Metrics and logs

WebSocket activity produces three events, which appear in [Real-Time Metrics](/en/documentation/platform/real-time-metrics/) and [Data Stream](/en/documentation/platform/data-stream/) to help you monitor connections and messages:

- `websocket.connection.accepted`
- `message.sent`
- `message.received`

---

## Firewall inspection

The rules of a [firewall](/en/documentation/platform/firewall/) can inspect WebSocket traffic before the upgrade completes. Check that your firewall rules let through the WebSocket connections that your function must accept.

---

## Example

This handler accepts a WebSocket upgrade when the request carries `upgrade: websocket`, logs the `open`, `message`, `close`, and `error` events of the socket, and answers each message with `pong`. Any other request receives an HTML page whose script opens a WebSocket connection back to the same host:

```javascript
export default {
    async fetch(request, env, ctx) {
        // Check if the request is a WebSocket upgrade
        if (request.headers.get("upgrade") === "websocket") {
            // Use the upgradeWebSocket function to handle the WebSocket upgrade
            const { response, socket } = upgradeWebSocket(request);

            // Handle WebSocket events
            socket.addEventListener("open", () => {
                console.log("WebSocket connection established");
            });

            socket.addEventListener("message", (event) => {
                console.log(`Message received: ${event.data}`);
                socket.send("pong"); // Respond with "pong"
            });

            socket.addEventListener("close", () => {
                console.log("WebSocket connection closed");
            });

            socket.addEventListener("error", (error) => {
                console.error("WebSocket error:", error);
            });

            // Return the response to complete the WebSocket upgrade
            return response;
        }

        // If the request is not a WebSocket upgrade, serve a simple HTML page
        const htmlContent = `
            <!DOCTYPE html>
            <html>
            <head>
                <title>WebSocket Example</title>
            </head>
            <body>
                <h1>WebSocket Example</h1>
                <script>
                    const socket = new WebSocket("wss://" + location.host);
                    socket.onopen = () => console.log("WebSocket connected");
                    socket.onmessage = (event) => console.log("Message from server:", event.data);
                    socket.onclose = () => console.log("WebSocket disconnected");
                    socket.onerror = (error) => console.error("WebSocket error:", error);
                </script>
            </body>
            </html>
        `;

        return new Response(htmlContent, {
            status: 200,
            headers: { "Content-Type": "text/html" },
        });
    },
};
```

A deployed function returns this response to a request without the `upgrade` header. The body is the HTML page, with its line breaks escaped:

```json
{
 "status": 200,
 "statusText": "",
 "headers": {
  "content-type": "text/html"
 },
 "body": "\n            <!DOCTYPE html>\n            <html>\n            <head>\n                <title>WebSocket Example</title>\n            </head>\n            <body>\n                <h1>WebSocket Example</h1>\n                <script>\n                    const socket = new WebSocket(\"wss://\" + location.host);\n                    socket.onopen = () => console.log(\"WebSocket connected\");\n                    socket.onmessage = (event) => console.log(\"Message from server:\", event.data);\n                    socket.onclose = () => console.log(\"WebSocket disconnected\");\n                    socket.onerror = (error) => console.error(\"WebSocket error:\", error);\n                </script>\n            </body>\n            </html>\n        "
}
```

---

## Related resources

- [WebSocket Proxy](/en/documentation/platform/applications/websocket.md): How an application carries a WebSocket connection to a server at your origin.
- [Handlers](/en/documentation/devtools/runtime/api-reference/handlers.md): The handler shape that receives the request and returns the upgrade response.
- [Request](/en/documentation/devtools/runtime/api-reference/request.md): How a function reads the headers of the incoming request, such as `upgrade`.
- [Web APIs](/en/documentation/devtools/runtime/api-reference/javascript.md): The other Web APIs that Azion Runtime supports.
