WebSockets
WebSockets work on StackBlaze web apps. Connect to the app’s platform hostname (or a custom domain you attached).
Connect to the platform hostname
Use wss:// against the app’s *.stackblaze.app URL — for example wss://my-service.stackblaze.app/ws. Copy the exact host from the app if yours includes a region segment. Custom domains work the same way over wss:// after DNS and TLS are in place.
Your process should accept the WebSocket upgrade on the port from PORT. Server-Sent Events work on the same public URL.
Libraries
Common WebSocket libraries work without a StackBlaze-specific adapter:
ws (Node.js)
import { WebSocketServer } from 'ws'
import { createServer } from 'http'
const server = createServer(app)
const wss = new WebSocketServer({ server })
wss.on('connection', (ws) => {
ws.on('message', (data) => {
ws.send(data.toString())
})
const interval = setInterval(() => ws.ping(), 30_000)
ws.on('close', () => clearInterval(interval))
})
server.listen(process.env.PORT || 8080)Socket.IO
import { createServer } from 'http'
import { Server } from 'socket.io'
const httpServer = createServer(app)
const io = new Server(httpServer, {
cors: {
origin: process.env.ALLOWED_ORIGINS?.split(',') ?? '*',
methods: ['GET', 'POST'],
},
transports: ['websocket', 'polling'],
})
io.on('connection', (socket) => {
socket.on('join-room', (roomId) => {
socket.join(roomId)
})
})
httpServer.listen(process.env.PORT || 8080)Server-Sent Events (SSE)
app.get('/events', (req, res) => {
res.writeHead(200, {
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive',
'X-Accel-Buffering': 'no',
})
const send = (data: object) => {
res.write(`data: ${JSON.stringify(data)}\n\n`)
}
send({ type: 'connected' })
const interval = setInterval(() => {
send({ type: 'heartbeat', timestamp: Date.now() })
}, 15_000)
req.on('close', () => {
clearInterval(interval)
})
})Keep-alives
const ws = new WebSocket('wss://my-service.stackblaze.app/ws')
const ping = setInterval(() => {
if (ws.readyState === WebSocket.OPEN) {
ws.send(JSON.stringify({ type: 'ping' }))
}
}, 30_000)
ws.addEventListener('close', () => clearInterval(ping))More than one replica
A WebSocket stays on the replica that accepted it. To broadcast to every connected client, use a shared pub/sub (for example Redis attached in the same phase) so each replica can fan out to its local sockets.
Socket.IO Redis adapter
import { createAdapter } from '@socket.io/redis-adapter'
import { createClient } from 'redis'
const pubClient = createClient({ url: process.env.REDIS_URL })
const subClient = pubClient.duplicate()
await Promise.all([pubClient.connect(), subClient.connect()])
io.adapter(createAdapter(pubClient, subClient))
io.emit('announcement', { message: 'Server update in 5 minutes' })