---
term: 'WebSockets & Real-Time Sync'
seoTitle: 'What are WebSockets? Real-Time Sync Explained'
headline: 'What are WebSockets?'
slug: websockets-real-time-sync
category: api-realtime
shortDefinition: 'A WebSocket is a persistent, two-way connection between client and server, letting either side push messages the instant they happen.'
relatedTerms:
  - real-time-live-queries
  - event-driven-architecture
  - webhooks
  - push-notifications-apns-fcm
  - sse-vs-websockets-vs-polling
contrastsWith:
  - webhooks
aboutTerms:
  - 'WebSockets'
  - 'Real-Time Synchronization'
faq:
  - question: 'What is a WebSocket in simple terms?'
    answer: 'A phone call instead of a mail exchange. HTTP is request-response — the client asks, the server answers, the line closes. A WebSocket opens one persistent connection over which both sides can send messages at any moment, with a few bytes of framing per message instead of full headers. It is the standard transport (RFC 6455) for chat, live data, and collaboration.'
  - question: 'How is a WebSocket different from HTTP?'
    answer: 'Direction and lifetime. HTTP is stateless and client-initiated: every exchange is a fresh request with full headers, and the server can never speak first. A WebSocket starts as an HTTP request, upgrades, and becomes a stateful, full-duplex channel where the server pushes without being asked — which is the entire point for anything that changes while the user watches.'
  - question: 'How does the WebSocket handshake work?'
    answer: 'It begins as polite HTTP: the client sends a GET with Upgrade and Connection headers plus a random Sec-WebSocket-Key; the server answers 101 Switching Protocols with an accept hash derived from that key. From that moment the TCP connection stops speaking HTTP and carries lightweight WebSocket frames in both directions until either side closes it.'
  - question: 'What is the difference between ws:// and wss://?'
    answer: 'The same difference as http and https: wss runs the connection over TLS. Production traffic is always wss — for privacy, and pragmatically because encrypted connections pass through proxies and corporate middleboxes that mangle plaintext upgrades. There is no legitimate reason to ship ws in production.'
  - question: 'What is the difference between WebSockets and Server-Sent Events?'
    answer: 'Direction. SSE is one-way — server streams to client over plain HTTP, with automatic reconnection built in — ideal for feeds, tickers, and notifications. WebSockets are two-way, for anything where the client also talks: chat, games, collaborative editing. SSE is simpler where it suffices; WebSockets are the general tool.'
  - question: 'How do reconnections and heartbeats work?'
    answer: 'The protocol includes ping/pong control frames so each side can verify the other is alive; applications layer heartbeats on top to detect half-dead connections, then reconnect with exponential backoff plus jitter and resubscribe their state. Managed real-time layers handle this loop for you — hand-rolled WebSocket code that skips it works right up until networks behave like networks.'
  - question: 'Do WebSockets scale?'
    answer: 'Yes, with different mechanics than HTTP: connections are stateful, so load balancers need session affinity; broadcasting to many clients needs a pub/sub backplane so every server node can fan out messages; and slow consumers need backpressure handling so one stalled client cannot balloon memory. These are solved problems — in infrastructure you either build or rent.'
  - question: 'When should you NOT use WebSockets?'
    answer: 'When request-response already fits: fetching cacheable resources, standard CRUD, infrequent updates. A persistent connection buys instant push and pays for it in statefulness — pointless for data that changes rarely. The rule of thumb: if polling every 30 seconds would genuinely suffice, skip the socket.'
codeLanguages: [javascript, dart, swift, kotlin]
externalAuthorities:
  - name: 'RFC 6455 — The WebSocket Protocol'
    url: 'https://www.rfc-editor.org/rfc/rfc6455'
  - name: 'WebSockets API — MDN Web Docs'
    url: 'https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API'
  - name: 'LiveQuery protocol specification'
    url: 'https://github.com/parse-community/parse-server/wiki/Parse-LiveQuery-Protocol-Specification'
  - name: 'Back4app Live Query documentation'
    url: 'https://www.back4app.com/docs/platform/parse-server-live-query-example'
cta:
  title: 'Real-time without running the sockets'
  text: 'Back4app Live Queries put a query layer on top of managed WebSockets: subscribe to the data you care about and receive changes as events — connections, heartbeats, reconnection, and fan-out handled by the platform.'
  linkText: 'Start building free'
  linkUrl: 'https://www.back4app.com/signup'
author: 'Back4app Engineering'
publishedDate: '2026-07-27'
translationKey: websockets-real-time-sync
---

**A WebSocket is a persistent, two-way connection between client and server, letting either side push messages the instant they happen.** HTTP made the web by asking; WebSockets made it live by *listening* — one standardized upgrade ([RFC 6455](https://www.rfc-editor.org/rfc/rfc6455)) turns a request into an open channel, and everything real-time on the web — chat, presence, tickers, collaborative cursors — rides on it.

## Key takeaways

| Question | Answer |
| --- | --- |
| What it is | One persistent, full-duplex connection — server push, client send, same pipe |
| vs. HTTP | Stateless request-response vs. stateful open channel |
| The handshake | HTTP GET + Upgrade → 101 Switching Protocols → frames |
| Production rules | Always wss://, heartbeats + backoff reconnection, plan the fan-out |
| The higher layer | Real-time *sync* — queries and state over the socket, not raw messages |

## How the WebSocket Handshake Upgrade Works (HTTP 101)

```text
GET /chat HTTP/1.1                      ← starts as ordinary HTTP
Host: example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==

HTTP/1.1 101 Switching Protocols        ← and stops being HTTP here
Upgrade: websocket
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=

# From now on: tiny frames (2–14 bytes overhead), both directions,
# vs ~500+ bytes of headers for every single HTTP poll.
```

Most applications shouldn't hand-roll what comes next — the production idiom is a managed real-time layer where the socket, heartbeats, and reconnection are somebody else's code:

**JavaScript:**

```javascript
// JavaScript / Node.js — Back4app JS SDK (Live Query over WebSockets)
// One WebSocket, managed for you: connect, subscribe, reconnect
const query = new Parse.Query('Message');
query.equalTo('room', 'general');

const subscription = await query.subscribe();  // wss:// under the hood
subscription.on('create', (msg) => appendToChat(msg));
subscription.on('open', () => setStatus('live'));
// Later: subscription.unsubscribe();
```

**Flutter:**

```dart
// Flutter / Dart — Back4app Flutter SDK (Live Query over WebSockets)
// One WebSocket, managed for you: connect, subscribe, reconnect
final liveQuery = LiveQuery();
final query = QueryBuilder<ParseObject>(ParseObject('Message'))
  ..whereEqualTo('room', 'general');

final sub = await liveQuery.client.subscribe(query); // wss:// under the hood
sub.on(LiveQueryEvent.create, (msg) => appendToChat(msg));
```

**Swift:**

```swift
// iOS / Swift — Back4app Swift SDK (Live Query over WebSockets)
// One WebSocket, managed for you: connect, subscribe, reconnect
let query = Message.query("room" == "general")

let subscription = query.subscribeCallback   // wss:// under the hood
subscription?.handleEvent { _, event in
  if case .created(let msg) = event { appendToChat(msg) }
}
```

**Kotlin:**

```kotlin
// Android / Kotlin — Back4app Android SDK (Live Query over WebSockets)
// One WebSocket, managed for you: connect, subscribe, reconnect
val client = ParseLiveQueryClient.Factory.getClient()
val query = ParseQuery.getQuery<ParseObject>("Message")
query.whereEqualTo("room", "general")

val handling = client.subscribe(query)       // wss:// under the hood
handling.handleEvent(SubscriptionHandling.Event.CREATE) { _, msg ->
  appendToChat(msg)
}
```

## WebSockets vs. everything else that moves data

| Transport | Direction | How it works | Best for |
| --- | --- | --- | --- |
| Polling | Client asks repeatedly | Full request per check | Legacy fallback only |
| Long polling | Client asks, server stalls | One pending request per message | Compatibility fallback |
| SSE | Server → client only | Streamed HTTP, auto-reconnect | Feeds, tickers, notifications |
| **WebSocket** | **Both ways** | **Upgraded persistent TCP** | **Chat, games, collaboration, sync** |
| WebRTC | Peer ↔ peer | UDP media/data channels | Calls, video — signaled *via* WebSockets |

```mermaid
flowchart LR
  accTitle: HTTP polling versus a WebSocket connection
  accDescr: With polling, the client repeatedly sends full HTTP requests that mostly return nothing new; with a WebSocket, one upgraded connection stays open and the server pushes each message the moment it occurs.
  subgraph P["Polling"]
    c1["Client"] -->|"request #1 …empty"| s1["Server"]
    c1 -->|"request #2 …empty"| s1
    c1 -->|"request #3 …message!"| s1
  end
  subgraph W["WebSocket"]
    c2["Client"] <-->|"one open channel<br/>messages both ways, instantly"| s2["Server"]
  end
```

## Running sockets in production

Four concepts carry the operational load. **Session affinity:** connections are stateful, so load balancers must keep each client pinned to its server node. **Fan-out:** broadcasting one message to ten thousand subscribers across many nodes requires a pub/sub backplane between servers — the message travels server-to-server before it travels server-to-client. **Backpressure:** a slow phone on a bad network can't be allowed to buffer unbounded messages in your server's memory; drop, coalesce, or disconnect. **Liveness:** ping/pong frames plus application heartbeats detect half-dead connections, and clients reconnect with exponential backoff and jitter, then *resubscribe their state* — the step naive implementations forget. None of this is exotic; all of it is why "we'll just open a socket" becomes a platform decision.

## From messages to sync: the layer above

Raw WebSockets move bytes; applications want *state*. The step up is real-time **sync**: instead of hand-rolling message types and client-side bookkeeping, you subscribe to data — a query, a document, a channel — and the layer delivers precise change events, handles reconnect-and-catch-up, and applies server-side permissions per subscriber. That's the [live queries](/glossary/real-time-live-queries/) model: WebSockets as the transport, a query engine as the brain. If your WebSocket code is accumulating switch statements over message types, you are rebuilding this layer by hand.

## Common use cases

- **Chat and messaging** — the canonical case: both sides talk, instantly.
- **Presence** — who's online, who's typing: tiny messages, high frequency, both directions.
- **Collaborative editing** — shared documents and whiteboards, where cursor positions and edits stream continuously.
- **Live dashboards and tickers** — server-push of changing numbers; SSE also fits when one-way.
- **Multiplayer and location** — game state and moving map markers, where latency is the product.

## Do you need a socket? A decision matrix

| Reach for WebSockets when… | Plain HTTP is right when… |
| --- | --- |
| Users watch data that changes now | Data changes rarely or on demand |
| Both sides initiate messages | Only the client ever asks |
| Latency is user-visible (chat, games) | A 30-second poll would honestly do |
| Many small messages flow constantly | Responses are large and cacheable |
| You'll run (or rent) the fan-out | Nobody owns socket operations |

And the middle path the matrix hides: server-to-client-only cases (feeds, notifications) fit SSE with less machinery — the full transport comparison has its own entry in this glossary's registry.

## Limitations and trade-offs

- **Statefulness is the price of push.** Every open connection is server memory and a load-balancing constraint; HTTP's statelessness was carrying more weight than it seemed.
- **Networks hate long-lived connections.** Proxies, mobile radios, and laptops closing lids all sever sockets constantly — reconnection logic isn't an edge case, it's the main loop.
- **Security moves to the connection.** Authenticate at connect time, validate every message, enforce authorization per subscription — and always wss.
- **Caching doesn't exist here.** Everything pushed is computed and delivered per client; the CDN can't help you.
- **Hand-rolled sync is a trap.** The gap between "opened a socket" and "correct, reconnecting, permissioned state sync" is where the real engineering lives — which is precisely the layer worth renting.

## WebSockets on Back4app

Back4app is an open-source Backend-as-a-Service (BaaS) platform that combines a managed database, auto-generated REST and GraphQL APIs, authentication, file storage, and Cloud Code serverless functions. Its real-time layer is [Live Query](https://www.back4app.com/docs/platform/parse-server-live-query-example): the WebSocket transport, heartbeats, reconnection, and multi-node fan-out run as managed infrastructure (the [open LiveQuery protocol](https://github.com/parse-community/parse-server/wiki/Parse-LiveQuery-Protocol-Specification) underneath), while your code subscribes to *queries* and receives typed change events — with ACLs enforced per subscriber, so real-time never bypasses the permission model. The code tabs above are the entire client-side story.
