From 6c59ffc00fe936ed7f8803f6b6532520f62f0ccf Mon Sep 17 00:00:00 2001 From: Andrew Bulat Date: Wed, 23 Oct 2024 13:09:39 +0100 Subject: [PATCH] Add README section to explain "Connection limit exceeded" error and solutions Resolves ECO-4841 --- README.md | 20 ++++++++++++++++++++ docs/react.md | 1 + 2 files changed, 21 insertions(+) diff --git a/README.md b/README.md index 0f7c27796..92c9f6113 100644 --- a/README.md +++ b/README.md @@ -641,6 +641,26 @@ The issue is coming from the fact that when using App Router specifically depend Using `serverComponentsExternalPackages` opt-outs from using Next.js bundling for specific packages and uses native Node.js `require` instead. This is a common problem in App Router for a number of packages (for example, see next.js issue [vercel/next.js#52876](https://github.com/vercel/next.js/issues/52876)), and using `serverComponentsExternalPackages` is the recommended approach here. +#### "Connection limit exceeded" error during development + +If you're encountering a "Connection limit exceeded" error when trying to connect to Ably servers during the development of your application, and you notice spikes or linear increases in the connection count on the Ably dashboard for your app, this may be due to one of the following reasons: + +- If you're using Next.js, your `Ably.Realtime` client instance may be created multiple times on the server side (i.e., in a Node.js process) as you're developing your app, due to Next.js server side rendering your components. Note that even for "Client Components" (i.e., components with the 'use client' directive), [Next.js may still run the component code on the server in order to pre-render HTML](https://nextjs.org/docs/app/building-your-application/rendering/client-components#how-are-client-components-rendered). Depending on your client configuration options, those clients may also successfully open a connection to Ably servers from that Node.js process, which won't close until you restart your development server. + + The simplest fix is to use the `autoConnect` client option and check if the client is created on the server side with a simple window object check, like this: + + ```typescript + const client = new Ably.Realtime({ key: 'your-ably-api-key', autoConnect: typeof window !== 'undefined' }); + ``` + + This will prevent the client from connecting to Ably servers if it is created on the server side, while not affecting your client side components. + +- If you're using any React-based framework, you may be recreating the `Ably.Realtime` client instance on every component re-render. To avoid this, and to prevent potentially reaching the maximum connections limit on your account, move the client instantiation (`new Ably.Realtime`) outside of your components. You can find an example in our [React docs](./docs/react.md#Usage). + +- The connection limit error can be caused by the Hot Reloading mechanism of your development environment (called Fast Refresh in newer Next.js versions, or more generally, Hot Module Replacement - HMR). When you edit and save a file that contains a `new Ably.Realtime()` call in an environment that supports HMR (such as React, Vite, or Next.js apps), the file gets refreshed and creates a new `Ably.Realtime` client instance. However, the previous client remains in memory, unaware of the replacement, and stays connected to Ably's realtime systems. As a result, your connection count will keep increasing with each file edit as new clients are created. This only resets when you manually refresh the browser page, which closes all clients. This behavior applies to any development environment with an HMR mechanism implemented. + + The solution is simple: move the `new Ably.Realtime()` call to a separate file, such as `ably-client.js`, and export the client instance from there. This way, the client instance will only be recreated when you specifically make changes to the `ably-client.js` file, which should be far less frequent than changes in the rest of the codebase. + ## Contributing For guidance on how to contribute to this project, see the [CONTRIBUTING.md](CONTRIBUTING.md). diff --git a/docs/react.md b/docs/react.md index bd0d32afa..1b2630e00 100644 --- a/docs/react.md +++ b/docs/react.md @@ -36,6 +36,7 @@ The hooks are compatible with all versions of React above 16.8.0 Start by connecting your app to Ably using the `AblyProvider` component. See the [`ClientOptions` documentation](https://ably.com/docs/api/realtime-sdk/types?lang=javascript) for information about what options are available when creating an Ably client. If you want to use the `usePresence` or `usePresenceListener` hooks, you'll need to explicitly provide a `clientId`. The `AblyProvider` should be high in your component tree, wrapping every component which needs to access Ably. +Also, ensure that the `Ably.Realtime` instance is created outside of components to prevent it from being recreated on component re-renders. This will help avoid opening extra unnecessary connections to the Ably servers and potentially reaching the maximum connections limit on your account. ```jsx import { AblyProvider } from 'ably/react';