# How would you approach utilizing WebSocket for real-time communication: Step-by-

- Tool: Bubble
- Difficulty: Advanced
- Time required: 30-40 min
- Compatibility: All Bubble plans (external WebSocket services may require paid tiers)
- Last updated: March 2026

## TL;DR

Bubble has built-in real-time data updates via its database-to-element binding, but for faster real-time communication like chat or live dashboards, you can use WebSocket plugins or external services like Pusher or Ably. This tutorial covers Bubble's native real-time capabilities and how to extend them with WebSocket integrations.

## Overview: Real-Time Communication with WebSockets in Bubble

Bubble provides built-in real-time updates: when data changes in the database, elements bound to searches automatically refresh. For many apps, this is sufficient. But when you need sub-second updates — live chat, multiplayer features, real-time dashboards, or live notifications — you may need external WebSocket services. This tutorial covers both approaches.

## Before you start

- A Bubble app that needs real-time features
- Basic understanding of Bubble data binding and workflows
- An account with a WebSocket service like Pusher (optional, for external approach)
- The Toolbox plugin installed (for JavaScript-based WebSocket connections)

## Step-by-step guide

### 1. Understand Bubble's built-in real-time updates

Bubble's database has native real-time capabilities. When you bind a Repeating Group to a Do a Search for expression, it automatically updates when records are created, modified, or deleted. This happens through Bubble's internal WebSocket connection. Test this by opening two browser tabs of the same page and creating a record in one — the other tab should show the new record within 1-3 seconds without refreshing.

> Pro tip: Bubble's built-in real-time only works for data bound to page elements. Searches inside workflows do not auto-update.

**Expected result:** You understand that Bubble already provides real-time data binding for element-bound searches.

### 2. Identify when you need external WebSocket services

Bubble's native real-time has limitations: updates take 1-3 seconds (not instant), it only works for data-bound elements, and heavy real-time usage increases WU consumption. You need external WebSockets when you need sub-second message delivery (live chat), presence detection (showing who is online), real-time typing indicators, live cursor tracking, or when Bubble's polling creates too much WU overhead.

**Expected result:** You can evaluate whether Bubble's native real-time is sufficient or if you need external WebSocket services.

### 3. Set up Pusher as an external WebSocket service

Sign up at pusher.com and create a Channels app. Note your app_id, key, secret, and cluster. In Bubble, go to the Plugins tab and install the Toolbox plugin if not already installed. Create an API Connector call to Pusher's HTTP API for triggering events. Set the method to POST, URL to https://api-{cluster}.pusher.com/apps/{app_id}/events, and configure authentication using your Pusher credentials.

```
{
  "name": "new-message",
  "channel": "chat-room-123",
  "data": {
    "message": "Hello!",
    "sender": "user_abc",
    "timestamp": "2026-03-28T15:00:00Z"
  }
}
```

**Expected result:** Pusher is configured and ready to receive events from your Bubble backend workflows.

### 4. Subscribe to real-time events on the client side

On the page where users need real-time updates, add a Page is loaded workflow with a Run JavaScript action from the Toolbox plugin. Load the Pusher JavaScript client library and subscribe to your channel. When a new event arrives, use the JavaScript to Bubble bridge to pass the data back to Bubble, then display it using custom states or trigger a custom event. This creates a persistent connection that receives messages instantly.

```
// Load Pusher client (add to page header or Run JavaScript)
var pusher = new Pusher('YOUR_PUSHER_KEY', { cluster: 'us2' });
var channel = pusher.subscribe('chat-room-123');
channel.bind('new-message', function(data) {
  // Pass data back to Bubble via JavaScript to Bubble bridge
  bubble_fn_newMessage(JSON.stringify(data));
});
```

**Expected result:** The page listens for real-time events and receives them instantly when triggered.

### 5. Trigger events from backend workflows

When an action occurs that should notify other users in real time (e.g., a new chat message is sent), add the API Connector call to Pusher in your workflow. Pass the channel name and event data. Pusher broadcasts the event to all connected clients on that channel. Combine this with database writes — save the message to your database AND trigger the Pusher event so that users see it instantly while the database record is also persisted.

**Expected result:** Actions in your app trigger instant real-time notifications to all connected users on the relevant channel.

### 6. Build a real-time notification system

Create a Notification Data Type with fields for recipient (User), message (text), read (yes/no), and type (Option Set). When an event occurs (new order, new message, etc.), create a Notification record AND trigger a Pusher event on a user-specific channel (e.g., user-{unique_id}). On the frontend, subscribe to the user's channel and update a notification counter custom state when events arrive. Display unread notifications in a dropdown with a Repeating Group.

**Expected result:** Users receive instant notifications when relevant events occur, with a live-updating counter.

## Complete code example

File: `Workflow summary`

```text
REAL-TIME COMMUNICATION SUMMARY
=================================

APPROACH 1: Bubble's Built-in Real-Time (simplest)
  - Bind Repeating Groups to Do a Search for
  - Data auto-refreshes when records change
  - Latency: 1-3 seconds
  - No additional setup needed
  - Best for: dashboards, lists, activity feeds

APPROACH 2: External WebSocket Service (Pusher/Ably)
  Setup:
    1. Create Pusher account, get credentials
    2. API Connector: POST to Pusher trigger API
    3. Toolbox: Load Pusher JS client on page load
    4. Subscribe to channels, bind events

  Backend → Pusher (trigger event):
    API Connector POST:
      URL: https://api-{cluster}.pusher.com/apps/{id}/events
      Body: { name, channel, data }

  Pusher → Frontend (receive event):
    Run JavaScript:
      pusher.subscribe('channel').bind('event', callback)
      → bubble_fn_handler(data)

NOTIFICATION SYSTEM:
  Data Type: Notification
    - recipient (User)
    - message (text)
    - read (yes/no, default: no)
    - type (Option Set: Order, Message, Alert)
    - Created Date (auto)

  On event (e.g., new order):
    1. Create Notification record in DB
    2. Trigger Pusher event on user-{recipient_id} channel
    3. Frontend: increment notification counter custom state

  Notification UI:
    - Bell icon with badge showing unread count
    - Dropdown Repeating Group: Search Notifications
      where recipient = Current User AND read = no
    - Mark as read on click: Make Changes → read = yes

WHEN TO USE WHICH:
  Built-in: <3 sec latency OK, data-driven updates
  Pusher/Ably: sub-second needed, chat, typing indicators
  Both: combine for data persistence + instant delivery
```

## Common mistakes

- **Trying to use WebSockets for everything instead of leveraging Bubble's built-in real-time** — Bubble's native data binding already provides real-time updates with 1-3 second latency, which is sufficient for most use cases Fix: Start with Bubble's built-in real-time. Only add external WebSockets for features that specifically need sub-second delivery.
- **Not persisting data alongside real-time events** — WebSocket events are transient — if a user is offline when an event fires, they miss it. Without database records, the data is lost. Fix: Always save data to the database AND trigger the WebSocket event. The database serves as the source of truth.
- **Exposing WebSocket credentials in client-side code** — If your Pusher secret key is in client-side JavaScript, anyone can trigger events on your channels Fix: Only the public key should be in client-side code. Keep the secret key in backend workflows and API Connector calls.

## Best practices

- Start with Bubble's built-in real-time data binding before adding external services
- Always persist data to the database alongside WebSocket events for reliability
- Use user-specific channels for private notifications (e.g., user-{unique_id})
- Keep WebSocket secret keys in backend workflows, never in client-side JavaScript
- Implement reconnection logic in your JavaScript to handle dropped connections
- Monitor WebSocket connection counts and message volumes to stay within service limits

## Frequently asked questions

### Does Bubble have built-in WebSocket support?

Bubble uses WebSockets internally for its real-time data binding, but does not expose raw WebSocket connections to builders. For custom WebSocket needs, you must use an external service.

### How fast is Bubble's built-in real-time?

Typically 1-3 seconds for data changes to appear in bound elements. This is sufficient for dashboards and activity feeds but too slow for live chat.

### Which WebSocket service should I use?

Pusher is the most popular choice for Bubble integration. Ably and Socket.IO are alternatives. Choose based on pricing, geographic coverage, and your expected message volume.

### Does real-time communication increase my WU usage?

Bubble's built-in real-time uses WUs for each data refresh. External WebSocket services handle the real-time transport externally, potentially reducing WU usage compared to frequent database polling.

### Can I build a chat app using only Bubble's native features?

Yes, for basic chat. Store messages in a Data Type and display in a Repeating Group. Messages appear within 1-3 seconds. For instant delivery, add Pusher. RapidDev can help build production-grade real-time features in Bubble.

### How do I handle users going offline and coming back online?

The Pusher client automatically reconnects when the connection drops. When users come back online, load missed messages from the database (your source of truth) and display them in the Repeating Group.

---

Source: https://www.rapidevelopers.com/bubble-tutorial/utilizing-websocket-real-time-communication-bubble
© RapidDev — https://www.rapidevelopers.com/bubble-tutorial/utilizing-websocket-real-time-communication-bubble
