---
number: 37869
slug: 37869-change-in-realtime-js-affecting-node-js-22
published: 2025-08-12
discussion: https://github.com/orgs/supabase/discussions/37869
labels:
  - realtime
  - persist-in-search
page: https://supabase.com/changelog/37869-change-in-realtime-js-affecting-node-js-22
---

# Change in `realtime-js` affecting Node.js < 22

## What changed

Using `realtime-js` library in Node.js < 22 will require to set transport for Realtime

## What do I need to do

**For most users (Browser, Node.js 22+):** No changes required
**For Node.js < 22 users:** You’ll need to make a small change to explicitly set the WebSocket transport (see line 9 below).


```bash
npm i ws
```
```ts
import "dotenv/config";
import { createClient, SupabaseClient } from "@supabase/supabase-js";
import express, { Application } from "express";
import ws from "ws";

const supabaseUrl = process.env.SUPABASE_URL!;
const supabaseAnonKey = process.env.SUPABASE_ANON_KEY!;
const supabase: SupabaseClient = createClient(supabaseUrl, supabaseAnonKey, {
  // Explicitly set the WebSocket transport here
  realtime: { transport: ws as any },
});

const startRealtime = () =>
  supabase.channel("realtime:server").subscribe(console.log);

const app: Application = express();
startRealtime();
app.listen(3000);
```

> [!WARNING]  
> We are working on a fix for the type definition as currently it's not being accepted as a WebSocketLike interface.


## Why did we change it 
We have been facing multiple issues where the dynamic import of `ws` was breaking several runtimes and environments. The first environment where this become a serious issue was with Expo which required us to tackle the issue.


### Previous attempts
#### Multiple NPM entrypoints
PR: https://github.com/supabase/realtime-js/pull/476 

First approach chosen in conjunction with the Expo team but ended up creating several issues in other runtimes (namely Deno and Browser) so we reverted to use another method

#### Polymorphic client
PR: https://github.com/supabase/realtime-js/pull/485

Second approach chosen as it's usually the "default" as we accepted the overhead of having a polymorphic WS connector but this created issues with Vercel ( https://github.com/supabase/supabase-js/issues/1437 ) 

### Current approach
After our several attempts in handling how Javascript runtimes handle dynamic imports we had to change the way we support Node.js < 22 as it was the original source of the issue due to the lack of native WebSocket support

The changes are implemented in [realtime-js@2.15.1](https://www.npmjs.com/package/@supabase/realtime-js/v/2.15.1) with the changes from https://github.com/supabase/realtime-js/pull/514 
The changes are implemented in [supabase-js@2.55.0](https://www.npmjs.com/package/@supabase/supabase-js/v/2.55.0) with the changes from https://github.com/supabase/supabase-js/pull/1529 

We opted to use this approach as it fully prevents the usage of dynamic imports; it avoids external library issues; has a path for upgradability and avoids multiple entrypoints which proven to be error prone.
