Features
The hard part of realtime, already running
A realtime feature is a little product code on a lot of delivery machinery: who is subscribed, who is allowed, who is still there. PushCaster is that second part.
Channels
Four kinds, and the prefix is the contract
A channel's name decides how it behaves. The prefix tells the library whether to ask your server for authorisation, whether to expect a member list, and whether to encrypt.
| Prefix | Who can subscribe | What it is for | Auth |
|---|---|---|---|
| public | Anyone with the app key. | Build status, live scores, public feeds. | None |
| private- | Your server decides, per subscriber. | Anything scoped to an account or resource. | Signed |
| presence- | Authorised, and carries the member list. | Rooms and sessions, where membership is the feature. | Signed |
| private-encrypted- | Authorised; payloads encrypted by your clients. | Payloads that should stay opaque to us too. | Signed |
cache- channels deliver live events but do not replay stored state — see known differences.
Authorisation
Your server stays the authority
We do not grant private and presence subscriptions. Your application does, and signs its answer with your app secret. We verify the signature and nothing else.
- One endpointPOST /pusher/auth keeps its request and response shape.
- Your rulesWhether this socket may join this channel is a question only you can answer.
- Presence identityThe same call returns the member id and whatever other members should see.
import Pusher from 'pusher'const pusher = new Pusher({ appId: process.env.PUSHCASTER_APP_ID, key: process.env.PUSHCASTER_KEY, secret: process.env.PUSHCASTER_SECRET, host: 'api-eu1.pushcaster.io', useTLS: true,})// Called by the client library whenever it subscribes to a// private-, presence- or private-encrypted- channel.app.post('/pusher/auth', (req, res) => { const { socket_id, channel_name } = req.body const user = req.session.user if (!user || !mayJoin(user, channel_name)) { return res.sendStatus(403) } res.send( pusher.authorizeChannel(socket_id, channel_name, { user_id: String(user.id), user_info: { name: user.name }, }), )})Webhooks
What the socket layer sees, your backend hears
Occupancy and membership are only visible at the connection. Webhooks post them back, signed — so you can start work when the first viewer arrives and stop when the last leaves.
| Event | Fires when |
|---|---|
| channel_occupied | First subscriber joined an empty channel. |
| channel_vacated | The last subscriber left. |
| member_added | Someone joined a presence channel. |
| member_removed | Someone left a presence channel. |
| client_event | A client sent an event directly to a channel. |
| cache_miss | A cache channel was asked for state it did not hold. |
app.post('/pushcaster/webhooks', (req, res) => { const hook = pusher.webhook({ headers: req.headers, rawBody: req.rawBody }) // The signature is computed with your app secret, so an // unsigned or mismatched delivery never reaches your logic. if (!hook.isValid()) return res.sendStatus(401) for (const event of hook.getEvents()) { if (event.name === 'channel_occupied') startFeed(event.channel) if (event.name === 'channel_vacated') stopFeed(event.channel) } res.sendStatus(200)})Libraries
There is no PushCaster SDK, on purpose
PushCaster speaks the Pusher Channels protocol on the wire, so the official libraries work against it unmodified. No package of ours to add, and nothing that breaks when we ship.
- pusher-js
- Laravel Echo
- pusher/pusher-php-server
- pusher-http-node
- Python
- Go
- Ruby
- Java
- Android
- iOS
- Flutter
- Unity
Install line, in full: npm i pusher-js.
Infrastructure
Two planes, and a cluster you choose
Delivery runs on a plane separate from billing and configuration, so a control-plane outage degrades the dashboard without interrupting delivery.
Running now
- eu1Europe West
- eu2Europe Central
Clusters are highly available for messaging and not for presence: if a presence store is lost, presence and occupancy degrade while public and private channels keep delivering. Better read here than discovered later.
See how a publish travels