All posts

Pusher, Soketi or Thunderclap? Choosing a realtime backend in 2026

Prices and project status checked on 1 November 2026.

If you're adding live updates to a product (chat, notifications, dashboards, presence, a live score), you'll end up choosing between three shapes of the same idea: channels you publish to from your backend, and clients that subscribe over a WebSocket. Pusher made that model popular. Soketi made it self-hostable. Thunderclap rebuilds it to scale on its own and cost nothing while it's quiet.

This article compares the three the way you'd evaluate them for a real product: how they're built, what they cost for typical workloads, how they scale, and where each one is the better choice. Including where it isn't us.

The short version

PusherSoketiThunderclap
What it isManaged serviceOpen-source server you hostManaged service
Where your users connectOne region per appWherever you deploy itThe nearest edge location, worldwide
How you scalePick a bigger planAdd nodes, and Redis behind themNothing to do: capacity appears as it's needed
What you pay forConnections and every deliveryYour servers and your team's timeConnections and messages published: fan-out is free
Idle connectionsCount toward your planCost whatever the servers costFree
Knowing what a client missedNoNoYes: sequence numbers and gap events

If you remember one thing: Pusher bills you for each delivery, Thunderclap bills you for each message you publish. One message to a 30-person room is 31 messages on Pusher and 1 on Thunderclap. The more your messages fan out, the wider the gap.

Three ways to build the same thing

Pusher: a managed cluster in one region

Pusher: users everywhere connect to one cluster in one region, and so does the backend.SydneyTokyoSão PauloLondonNew YorkPusher clusterone region: us-east-1Your backendpublishesEvery frame goes through us-east-1,wherever the user is.
Pusher: one region per app. A user in Sydney on a US app crosses the Pacific for every message.

You create an app in a cluster (mt1, eu, ap1…), and every client and your backend talk to that region. It's simple and it's been reliable for over a decade. The trade-off is geography: a user in Sydney connected to a US app crosses the Pacific for every frame, and serving several regions means several apps, with your backend publishing to each.

Soketi: your own cluster, glued together with pub/sub

Soketi: clients reach nodes through a load balancer, and Redis sends every message to every node.Load balancersoketi node 13 subscriberssoketi node 22 subscriberssoketi node 3no subscribersRedis pub/subone topic, every messageYour backendNode 3 still receives and decodes every message.
Soketi: each publish goes through one Redis topic to every node, including nodes with nobody to deliver it to.

Soketi is an open-source server that speaks Pusher's protocol, so Pusher's client and server libraries work against it unchanged. A single node is fast: it's built on uWebSockets.js. To run several, nodes share messages through Redis or NATS, and that's where its scaling model shows:

It's also worth knowing where the project stands: the last release, 1.6.1, is from March 2024, and it depends on a 2022 version of uWebSockets.js, so running it on a current Node.js may mean rebuilding it yourself.

Thunderclap: an actor mesh at the edge

Thunderclap: shards hold sockets near users; a channel sends each event once to each shard with subscribers.Edge · FrankfurtEdge · Tokyoshard 13 in room-42shard 2none in room-42shard 32 in room-42channel room-42numbers every eventYour backendpublishes onceOne copy per shard,not per subscriber.
Thunderclap: sockets end at the nearest location. The channel sends one copy per shard with subscribers; shard 2 never sees room-42's events.

Thunderclap is a managed service built from two kinds of small, stateful actors, running in edge locations around the world:

Three consequences matter to you as a user:

  1. A message only travels where it's needed. Unlike a pub/sub cluster, a shard with no subscribers to a channel never sees its messages, so publish capacity grows with the number of channels instead of being capped by one node.
  2. Big rooms don't create big storms. If 100,000 people join one channel, the channel hears from the shards they land on (dozens, not 100,000). Shards absorb the subscribe storm.
  3. Clients know what they missed. Because one actor orders each channel, every event carries a sequence number. After a network drop, thunderclapJS tells you exactly which range to fetch from your own database:
client.ts
room.onGap((gap) => {
  if (gap.reset) reloadRecentHistory();
  else fetchMissed({ from: gap.from, to: gap.to });
});

Neither Pusher nor Soketi can do this: a reconnecting client simply doesn't know whether it missed anything.

What it costs

Two different ways of counting

PusherThunderclap
A publish to 50 subscribers counts as51 messages1 message
Message allowance isper day (your busiest day sets the tier)per month
Connections billed atyour plan's maximumthe 95th percentile of hourly peaks (a few hours of spike don't set the bill)
Going overupgrade to the next tierpay-as-you-go on any paid plan: $2 per 1,000 connections, $4 per million messages
Entry paid plan$49: 500 connections, 1M messages a day$29: 5,000 connections, 8M messages a month
$99 plan2,000 connections, 4M messages a day25,000 connections, 25M messages a month

At the two prices both sell a plan at, the difference in connections is more than tenfold:

Connections included at the same price

Peak concurrent connections included in the $99 and $499 plans.

PusherThunderclap

Pusher Pro and Premium, Thunderclap Pro and Business. List prices on 1 November 2026.

Pusher's published tiers go from Sandbox (free, 100 connections) to Growth Plus ($1,199: 30,000 connections, 90M messages a day), then Enterprise. Thunderclap's go from Spark (free, 200 connections, 2M messages) to Business ($499: 150,000 connections, 120M messages), then Enterprise, and paid plans are never capped.

Soketi is free software, so its cost is infrastructure plus the people who run it. A minimal highly available setup (two nodes, Redis, a load balancer) is roughly $20–40 a month on budget cloud providers. The people cost is the bigger number: even a tenth of an engineer's time spent on upgrades, scaling and on-call is worth far more than any plan in the examples below.

Three real workloads

Monthly bills, 30 days, at list prices. For each one we picked the cheapest Pusher tier and the cheapest Thunderclap plan (plus overage) that fit.

Notifications: one recipient per message. 2,000 peak connections, each user getting a notification every 5 minutes on their own private channel. That's 17.3M messages published a month.

Team chat: 30-person rooms. 10,000 peak connections, each user receiving one message a minute. 14.4M messages published, 432M deliveries.

Live broadcast: one channel, many viewers. 50,000 viewers around the clock, one update a second. 2.6M messages published, 130 billion deliveries.

WorkloadPusherThunderclapSoketi (servers only)
Notifications, 2k connections$99$66~$20–40
Chat rooms, 10k connections$499$65~$20–40
Broadcast, 50k viewersEnterprise (custom)$119~$40–100

Monthly bill, same workload

Notifications for 2,000 users and chat rooms for 10,000: the cheapest plan, plus overage, that fits each.

PusherThunderclap

List prices on 1 November 2026. The 50,000-viewer broadcast isn't shown: Pusher has no public price for it.

The pattern: the more your messages fan out, the more you save against Pusher, from about 1.5× with one recipient per message to 7–8× for rooms, and a public price instead of a sales call for broadcasts. Against Soketi, Thunderclap costs more in raw infrastructure once traffic is steady, and less once you count the time it takes to run Soketi well.

How they scale

PusherSoketiThunderclap
More connectionsUpgrade your plan; above it, talk to salesAdd nodes; existing sockets don't rebalanceAutomatic: new shards appear as users arrive
A sudden connect storm (a launch, a viral moment)Pusher's problem, within your planHits the nodes you have: over-provision for itSplit across edge locations, each absorbing its share. We opened 50,000 clients in 10 seconds from 10 regions, and every one connected
Publish throughput, whole appOpaqueCapped by what one node can ingest, since every node gets every messageGrows with your number of channels: each one is its own actor
One very busy channelOpaqueFine: every node gets every message anywayFans out directly to its shards; measured ~9,500 deliveries a second per shard
Presence100 members per channelConfigurable, but every join asks every node100 members per channel (larger presence is on the roadmap)
When nobody's aroundYour plan's feeYour servers keep runningClose to zero: sleeping shards hold sockets for free

Our capacity numbers, how we measured them and what they imply for your workload are in a companion article: How far does Thunderclap scale?

Features side by side

PusherSoketiThunderclap
Public, private and presence channelsYesYesYes
Client eventsYesYesYes (opt-in per app)
WebhooksYesYes, through a queue you runYes: several endpoints per app, signed with every active secret so they keep verifying during a secret rotation
Sequence numbers and gap detectionNoNoYes
Token auth that covers many channels in one go (no auth request per subscribe)NoNoYes: connection tokens, plus per-channel auth when you need it
Listing every channel in an appYesYes (asks every node)No, by design: channels are independent, which is what lets them scale
Client SDKsJavaScript, iOS, Android, Flutter and moreUses Pusher'sJavaScript/TypeScript: browsers, React Native, Node.js, Deno, Bun
Server SDKsPHP, Ruby, Python, Go, Java, .NET, Node.js…Uses Pusher'sNode.js/TypeScript, including edge runtimes. More languages are on the roadmap
Local developmentCloud sandboxRun itThunderclap Local: a Docker image for development, tests and CI

Choosing

Pick Pusher if

Pick Soketi if

Pick Thunderclap if

What we're honest about

Switching

From Pusher or Soketi, the first step is a configuration change: Thunderclap understands Pusher's protocol and REST API, so your existing client and server libraries work by changing the host. Then you move to thunderclapJS and @thunderclapjs/server at your own pace, page by page if you like, because clients on both share the same channels. The migration guide walks through both steps.

Starting fresh, it's two packages:

client.ts
import { Thunderclap } from "@thunderclapjs/client";

const thunderclap = new Thunderclap({ key: process.env.NEXT_PUBLIC_THUNDERCLAP_KEY });
thunderclap.subscribe("room-42").bind("message", (data, meta) => show(data, meta.seq));
server.ts
import { ThunderclapServer } from "@thunderclapjs/server";

const thunderclap = new ThunderclapServer({
  appId: process.env.THUNDERCLAP_APP_ID,
  secret: process.env.THUNDERCLAP_SECRET,
});
await thunderclap.publish({ channel: "room-42", data: { text: "Hello!" } });

The free plan, Spark, includes 200 connections and 2 million messages a month, with no card. The quickstart gets you to a first event in a few minutes.

Pusher's prices are from pusher.com/channels/pricing and Soketi's status from its GitHub repository, both read on 1 November 2026. Self-hosting costs are approximate. Thunderclap's figures come from our own load tests, described in How far does Thunderclap scale?