All notable changes to this project are documented here. Format based on Keep a Changelog, versioning follows Semantic Versioning.
[Unreleased]
[0.2.0]
Changed (breaking)
- Renamed from
pusher_serverto Socketelx. The Hex package, OTP app and release aresocketelx, the main module isSocketelx(wasPusherServer), and the Docker image issocketelx. Update{:pusher_server, ...}to{:socketelx, ...}and{PusherServer, ...}to{Socketelx, ...}. - Environment variables are now
SOCKETELX_*. The oldPUSHER_*names are still accepted, andSOCKETELX_*wins when both are set. - Metric names start with
socketelx_(waspusher_server_), and Redis keys start withsocketelx:(waspusher:). Redis state is ephemeral, so nothing needs migrating.
Added
Socketelx.trigger/5publishes an event straight from your Elixir code, andSocketelx.authorize_channel/4signs private and presence channel joins, so an embedded app needs no HTTP round trip.examples/chat: a complete chat app (presence, messages, typing indicator) as a standalone Docker version and an embedded Elixir version, with a smoke test.bench/load.mjsand a load-testing guide to simulate many connections.- Documentation reworked around
pusher-jsand the official Pusher server libraries; Laravel setup moved to its own guide. POST /apps/:app_id/batch_events(up to 10 events per request) andGET /apps/:app_id/channels(withfilter_by_prefixandinfo=user_count), both working across nodes with Redis.- The Docker workflow can also publish to Docker Hub, and tags semver versions and
latest. SOCKETELX_BATCH_LIMIT(default 10) sets thebatch_eventssize limit.- Webhook retries with exponential backoff (
SOCKETELX_WEBHOOK_RETRIES, default 3). 5xx, 408, 429 and network errors are retried; other 4xx are not. - Optional limits, all off by default:
SOCKETELX_REST_RATE_LIMIT,SOCKETELX_CLIENT_EVENT_RATE_LIMIT,SOCKETELX_MAX_CONNECTIONS. - Optional Prometheus metrics at
GET /metrics(SOCKETELX_METRICS,SOCKETELX_METRICS_TOKEN). - Multi-server mode: set
SOCKETELX_REDIS_URL(or the:redis_urloption) and several nodes share broadcasts, presence and channel occupancy through Redis. A janitor heartbeats each node, removes state left by dead nodes and rebuilds a node's state if Redis loses its data. Single-node use is unchanged and still needs no Redis. deploy/nginx.confand a two-nodedocker-compose.example.yml- Redis service in CI so the multi-node tests run there
- User guides (
guides/), grouped API docs, CONTRIBUTING, SECURITY, code of conduct, and issue / PR templates - A warning is logged when the public default app secret is in use
Changed
- The server now advertises a 30 s
activity_timeoutand closes connections silent for 60 s. Both were 120 s, so a quiet client's ping could race the server's own idle timeout.
Fixed
- Several ExDoc warnings (hidden-function links, missing
Config.t()type). - Graceful shutdown never reached clients: the drain ran in
Application.stop/1, which OTP calls after the supervision tree is gone. It now runs inprep_stop/1, with a regression test. - CI's
mix format --check-formattedstep would have failed; the code is now formatted and.formatter.exsknows theplugmacro. config/runtime.exsno longer starts a listener undermix test.- Dockerfile copies
mix.lockwhen present.
[0.1.0] - 2026-07-09
Added
- Pusher protocol websocket handshake, subscribe/unsubscribe, ping/pong
- Private and presence channel auth (HMAC-SHA256)
- Presence membership tracking, deduped by
user_idacross connections - REST trigger endpoint (
POST /apps/:app_id/events) - Client events (
client-*) on private/presence channels - Webhooks (
channel_occupied/vacated,member_added/removed,client_event) - Read-only channel info endpoint (
GET /apps/:app_id/channels/:channel) - Graceful shutdown (drains connections on SIGTERM) and idle connection timeout
- Test suite for signature verification, presence semantics, and webhook payloads
Known limitations
- Redis Cluster (sharded) is not supported; use a single Redis endpoint
- No SSL termination built in (put a reverse proxy in front)
- No rate limiting or connection caps
- No batch events endpoint