Pulse is a high-performance, self-hosted WebSocket server that implements the Pusher protocol for real-time bidirectional messaging. It is a fork of Soketi with significant enhancements, modernized dependencies, and production-ready features built on top of uWebSockets.js — a C++-compiled WebSocket and HTTP library.
It provides a drop-in replacement for Pusher.com Channels, allowing you to run your own real-time infrastructure behind your firewall, on your own hardware, or in any cloud environment.
- Pusher Protocol Compatible — Works seamlessly with Pusher JS SDK, Laravel Echo, and Pusher backend SDKs (PHP, Node.js, Python, etc.)
- High Performance — Powered by uWebSockets.js, a C++-native engine capable of tens of thousands of concurrent connections
- Node.js v18 – v24 Support — Fully compatible with the latest Node.js runtimes up to version 24
- Channel Types — Public, Private, Encrypted Private, and Presence channels
- Client Events — Enable client-to-client messaging on private channels
- Horizontal Scaling — Multiple adapters: Local, Redis, NATS, Cluster
- Rate Limiting — Granular rate limiting for backend events, client events, and read requests
- Webhooks — HTTP webhook notifications with optional AWS Lambda support
- Webhook Logger — Persist webhook deliveries to daily log files (webhook-YYYY-MM-DD.log) or database (MySQL/PostgreSQL)
- Production-Ready Bundling — Single-file bundle via esbuild for zero-dependency deployment
- Prometheus Metrics — Expose real-time server metrics on a dedicated HTTP endpoint
- Queue System — Async event processing via sync or Redis (BullMQ)
- Multi-App Support — Serve multiple applications with isolated credentials
- Graceful Shutdown — Drain active connections before terminating
- SSL/TLS Support — Serve secure WSS connections
- Docker Support — Containerized deployment ready
- PM2 Support — Process management via PM2 clustering
- CORS — Fully configurable CORS headers
- Why Pulse? (vs Soketi)
- Requirements
- Architecture Overview
- Installation
- Configuration
- Usage
- Channel Types
- Horizontal Scaling
- Webhook Logger
- Production Bundling
- Monitoring & Metrics
- API Endpoints
- Webhooks
- Rate Limiting
- Project Structure
- Development
- Known Limitations
- Contributing
- License
Pulse is a fork of Soketi — an excellent open-source WebSocket server. This fork introduces additional features and improvements that align with specific production requirements. We are grateful to the Soketi maintainers and contributors for their foundational work.
| Aspect | Soketi | Pulse |
|---|---|---|
| Node.js Support | v14 – v18 | v18 – v24 |
| Webhook Logging | Not available | File & Database (MySQL/PostgreSQL) |
| Production Bundling | Requires npm install on server | esbuild single-file bundle |
| Environment Prefix | SOKETI_ |
PULSE_ |
| AWS Lambda Webhooks | Not available | Supported |
| Database Pooling | Not available | Knex connection pooling |
| Graceful Shutdown | Basic | Configurable grace period |
| CLI Binary | soketi |
pulse |
| Dependency | Version |
|---|---|
| Node.js | v18 – v24 |
| npm | v8+ |
| Memory | Minimum 256 MB (recommended: 1 GB+) |
Optional:
- Redis — For Redis adapter, rate limiter, cache, and queue
- NATS — For NATS adapter
- MySQL / PostgreSQL — For database-backed app managers and webhook logging
- Docker — Containerized deployment
- PM2 — Production process management
Note: Due to uWebSockets.js limitations, Pulse cannot run on CentOS 7. Tested on CentOS 8 and Ubuntu.
┌──────────────────────────────────────────────────────────────┐
│ Pulse Server │
├──────────────────────────────────────────────────────────────┤
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌────────────┐ │
│ │ HTTP │ │ WebSocket │ │ Metrics │ │ Queue │ │
│ │ Handler │ │ Handler │ │ (Prom) │ │ Processor │ │
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ └──────┬─────┘ │
│ │ │ │ │ │
│ ┌────▼─────────────▼─────────────▼───────────────▼──────┐ │
│ │ Core Engine │ │
│ │ (uWebSockets.js / Node.js) │ │
│ └────────────────────────┬──────────────────────────────┘ │
│ │ │
│ ┌────────────────────────▼──────────────────────────────┐ │
│ │ Adapter Layer │ │
│ │ ┌───────┐ ┌───────┐ ┌──────┐ ┌────────┐ │ │
│ │ │ Local │ │ Redis │ │ NATS │ │Cluster │ │ │
│ │ └───────┘ └───────┘ └──────┘ └────────┘ │ │
│ └───────────────────────────────────────────────────────┘ │
│ │
│ ┌───────────────────────────────────────────────────────┐ │
│ │ App Manager Layer │ │
│ │ ┌───────┐ ┌───────┐ ┌──────────┐ │ │
│ │ │ Array │ │ MySQL │ │PostgreSQL│ │ │
│ │ └───────┘ └───────┘ └──────────┘ │ │
│ └───────────────────────────────────────────────────────┘ │
│ │
│ ┌───────────────────────────────────────────────────────┐ │
│ │ Webhook Logger Layer │ │
│ │ ┌──────────────┐ ┌──────────────────┐ │ │
│ │ │ File Logger │ │ Database Logger │ │ │
│ │ │ (Daily Rotate)│ │ (MySQL/Postgres) │ │ │
│ │ └──────────────┘ └──────────────────┘ │ │
│ └───────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────┘
git clone https://github.com/oneaxxall/pulse.git
cd pulse
npm install
npm run build
npm linkNow use the pulse command anywhere:
pulse startdocker build -t pulse .
docker run -d --name pulse -p 6001:6001 pulseOr use docker-compose:
docker-compose up -dpm2 start pulse -- start./production.sh
# Creates pulse-production.tar.gz (~35MB)
# Contains a single bundled JS file — no npm install needed on target server!Configuration methods (in order of precedence):
- JSON config file —
pulse --config=app.json - Environment variables —
.envfile (prefix:PULSE_) - Default configuration — Defined in
src/server.ts
| Parameter | Default Value |
|---|---|
| App ID | app-id |
| App Key | app-key |
| App Secret | app-secret |
| Port | 6001 |
| Variable | Default | Description |
|---|---|---|
PULSE_DEBUG |
1 |
Enable debug logging |
PULSE_ADAPTER_DRIVER |
local |
Adapter driver |
PULSE_PORT |
6001 |
Server port |
PULSE_MANAGER_DRIVER |
array |
App manager driver |
PULSE_WEBHOOKS_LOGS_ENABLED |
false |
Enable webhook logging to files |
PULSE_WEBHOOKS_LOGS_DB_ENABLED |
false |
Enable webhook logging to database |
const pusher = new Pusher('app-key', {
wsHost: 'your-server.com',
wsPort: 6001,
forceTLS: false,
enabledTransports: ['ws', 'wss'],
});
const channel = pusher.subscribe('my-channel');
channel.bind('my-event', data => {
console.log('Received:', data);
});import Echo from 'laravel-echo';
window.Pusher = require('pusher-js');
window.Echo = new Echo({
broadcaster: 'pusher',
key: 'app-key',
wsHost: 'your-server.com',
wsPort: 6001,
forceTLS: false,
disableStats: true,
});$pusher = new Pusher\Pusher('app-key', 'app-secret', 'app-id', [
'host' => 'your-server.com',
'port' => 6001,
'scheme' => 'http',
]);
$pusher->trigger('my-channel', 'my-event', ['message' => 'Hello World!']);curl -X POST http://your-server.com:6001/apps/app-id/events \
-H "Content-Type: application/json" \
-d '{"name": "my-event", "channel": "my-channel", "data": "{\"message\":\"Hello World!\"}"}'| Type | Prefix | Description |
|---|---|---|
| Public | (none) | Open to all clients |
| Private | private- |
Requires auth; supports client events |
| Encrypted Private | private-encrypted- |
End-to-end encrypted private channel |
| Presence | presence- |
Tracks connected users |
| Cache | cache-* |
Caches channel state |
| Architecture | Adapter | Rate Limiter |
|---|---|---|
| Single node, single thread | local |
local |
| Single node, multi-thread (PM2) | cluster |
cluster |
| Multi-node, same network | cluster / redis |
cluster / redis |
| Multi-node, multi-network | redis |
redis |
Pulse includes a built-in Webhook Logger that persists all webhook deliveries for auditing, debugging, and compliance.
PULSE_WEBHOOKS_LOGS_ENABLED=true
PULSE_WEBHOOKS_LOGS_DIR=logsLog files are rotated daily: webhook-YYYY-MM-DD.log
PULSE_WEBHOOKS_LOGS_DB_ENABLED=trueNote: Database logging works with mysql/postgres manager driver. Run the SQL schema from
configurations/pds-pusher-manager.sql.
Pulse uses esbuild to compile the entire application into a single JavaScript file.
| Feature | Traditional | Pulse Bundled |
|---|---|---|
| npm install on server | Required | Not needed |
| Deployment size | ~200MB+ | ~35MB (compressed) |
| Startup time | Slow | Instant |
| Dependency conflicts | Possible | Eliminated |
| File count | Thousands | Single JS file |
./production.sh
# Output: pulse-production.tar.gz (~35MB)tar -xzf pulse-production.tar.gz
./run-pulse-server.shPulse exposes Prometheus-compatible metrics on port 9601:
PULSE_METRICS_ENABLED=true
PULSE_METRICS_SERVER_PORT=9601| Method | Endpoint | Description |
|---|---|---|
GET |
/ready |
Health check |
GET |
/health |
Detailed health |
GET |
/usage |
Memory usage |
GET |
/accept-traffic |
Traffic capacity check |
GET |
/apps/:appId/channels |
List channels |
POST |
/apps/:appId/events |
Trigger event |
POST |
/apps/:appId/events/batch |
Batch trigger events |
Events: client_event, channel_occupied, channel_vacated, member_added, member_removed. Supports AWS Lambda triggers.
| Limiter | Scope | Default |
|---|---|---|
| Backend events | POST /events | Unlimited (-1) |
| Client events | Per socket | Unlimited (-1) |
| Read requests | Read APIs | Unlimited (-1) |
pulse/
├── bin/ # CLI entry points
├── certs/ # SSL examples
├── configurations/ # DB schemas, Nginx, Supervisor configs
├── docs/ # Documentation
├── sdk/ # SDK examples
├── src/
│ ├── adapters/ # Local, Redis, NATS, Cluster adapters
│ ├── app-managers/ # Array, MySQL, PostgreSQL managers
│ ├── cache-managers/ # Memory, Redis cache
│ ├── channels/ # Public, private, presence, encrypted
│ ├── cli/ # CLI implementation
│ ├── metrics/ # Prometheus drivers
│ ├── queues/ # Sync, Redis queue drivers
│ ├── rate-limiters/ # Local, Redis, cluster
│ ├── types/ # TypeScript definitions
│ ├── webhook-log-adapters/ # File & DB webhook log storage
│ ├── server.ts # Core server
│ ├── ws-handler.ts # WebSocket handler
│ ├── http-handler.ts # REST API handler
│ └── webhook-logger.ts # Webhook logging system
├── tools/
│ └── build.js # esbuild bundling script
├── main.ts # Entry point
├── production.sh # Production bundling script
├── package.json
├── tsconfig.json
├── Dockerfile
└── docker-compose.yml
npm run dev # Hot-reload development
npm run build # Compile TypeScript
npm test # Run tests
npm run test:local # Verbose tests
npm run lint # Lint source
npm run bundle # Production bundle- CentOS 7 not supported
- Windows not extensively tested
- Subset of Pusher HTTP API implemented (core features complete)
- Fork the repository
- Create a feature branch
- Commit your changes
- Push and open a Pull Request
- Soketi — The original project that Pulse is forked from
- Pusher.com — For the protocol specification and inspiration
- uNetworking/uWebSockets.js — The high-performance WebSocket engine
- Laravel — For Laravel Echo and broadcasting integration
AGPL-3.0 License