{"id":45270173,"url":"https://github.com/silvermpx/wse","last_synced_at":"2026-03-07T01:04:04.511Z","repository":{"id":339831074,"uuid":"1162976542","full_name":"silvermpx/wse","owner":"silvermpx","description":"WSE - Rust-powered WebSocket engine for Python. Up to 2.1M del/s fan-out, zero-GIL JWT, E2E encryption","archived":false,"fork":false,"pushed_at":"2026-02-25T22:07:13.000Z","size":703,"stargazers_count":16,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-02-26T20:23:03.287Z","etag":null,"topics":["encryption","high-performance","jwt","pyo3","python","real-time","rust","tokio","websocket","websocket-server"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/silvermpx.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"docs/SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":"silvermpx"}},"created_at":"2026-02-20T23:23:52.000Z","updated_at":"2026-02-26T19:24:41.000Z","dependencies_parsed_at":"2026-02-26T16:01:02.133Z","dependency_job_id":null,"html_url":"https://github.com/silvermpx/wse","commit_stats":null,"previous_names":["silvermpx/wse"],"tags_count":24,"template":false,"template_full_name":null,"purl":"pkg:github/silvermpx/wse","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/silvermpx%2Fwse","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/silvermpx%2Fwse/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/silvermpx%2Fwse/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/silvermpx%2Fwse/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/silvermpx","download_url":"https://codeload.github.com/silvermpx/wse/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/silvermpx%2Fwse/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29905554,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-27T14:46:13.553Z","status":"ssl_error","status_checked_at":"2026-02-27T14:46:10.522Z","response_time":57,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["encryption","high-performance","jwt","pyo3","python","real-time","rust","tokio","websocket","websocket-server"],"created_at":"2026-02-21T01:10:08.428Z","updated_at":"2026-03-07T01:04:04.495Z","avatar_url":"https://github.com/silvermpx.png","language":"Python","readme":"# WSE - WebSocket Engine\n\n[![PyPI - Server](https://img.shields.io/pypi/v/wse-server)](https://pypi.org/project/wse-server/)\n[![PyPI - Client](https://img.shields.io/pypi/v/wse-client)](https://pypi.org/project/wse-client/)\n[![npm](https://img.shields.io/npm/v/wse-client)](https://www.npmjs.com/package/wse-client)\n[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)\n\nHigh-performance WebSocket server built in Rust with native clustering, E2E encryption, message recovery, presence tracking, and real-time fan-out. Exposed to Python via PyO3 with zero GIL overhead on the data path. Ships with Rust-accelerated utilities for application code: priority queues, rate limiters, event sequencing, compression, cryptography, and JWT.\n\n## Features\n\n### Server\n\n| Feature | Details |\n|---------|---------|\n| **Rust core** | tokio async runtime, tungstenite WebSocket transport, dedicated thread pool, zero GIL on the data path |\n| **JWT authentication** | HS256, RS256, ES256 algorithms via jsonwebtoken crate. Validated during handshake (0.01ms), cookie + Authorization header extraction, key rotation, kid validation |\n| **Protocol negotiation** | `client_hello`/`server_hello` handshake with feature discovery, capability advertisement, version agreement |\n| **Topic subscriptions** | Per-connection topic subscriptions with automatic cleanup on disconnect |\n| **Pre-framed broadcast** | WebSocket frame built once, shared via Arc across all connections, single allocation per broadcast |\n| **Vectored writes** | `write_vectored` (writev syscall) batches multiple frames per connection in a single kernel call |\n| **Write coalescing** | Write task drains up to 256 pending frames per iteration via `recv_many` |\n| **DashMap state** | Lock-free sharded concurrent hash maps for topics, rates, formats, activity tracking |\n| **mimalloc allocator** | Global allocator optimized for multi-threaded workloads with frequent small allocations |\n| **Deduplication** | 50,000-entry AHashSet with FIFO eviction per `send_event()` call |\n| **Rate limiting** | Per-connection token bucket: 100K capacity, 10K/s refill, client warning at 20% remaining |\n| **Zombie detection** | Server pings every 25s, force-closes connections with no activity for 60s |\n| **Drain mode** | Lock-free crossbeam bounded channel, Python acquires GIL once per batch (not per event) |\n| **Compression** | zlib for client-facing messages above threshold (default 1024 bytes) |\n| **MessagePack** | Opt-in binary transport via `?format=msgpack`, roughly 2x faster serialization, 30% smaller |\n| **Message signing** | Selective HMAC-SHA256 signing for critical operations, nonce-based replay prevention |\n\n### End-to-End Encryption\n\n| Feature | Details |\n|---------|---------|\n| **Key exchange** | ECDH P-256 (per-connection keypair, automatic during handshake) |\n| **Encryption** | AES-GCM-256 with unique 12-byte IV per message |\n| **Key derivation** | HKDF-SHA256 (salt: `wse-encryption`, info: `aes-gcm-key`) |\n| **Wire format** | `E:` prefix + 12-byte IV + AES-GCM ciphertext + 16-byte auth tag |\n| **Key rotation** | Configurable rotation interval (default 1 hour), automatic renegotiation |\n| **Replay prevention** | Nonce cache (10K entries, 5-minute TTL) on the client side |\n\n### Cluster Protocol\n\n| Feature | Details |\n|---------|---------|\n| **Topology** | Full TCP mesh, direct peer-to-peer connections |\n| **Wire format** | Custom binary frames: 8-byte header + topic + payload, 12 message types |\n| **Interest routing** | SUB/UNSUB/RESYNC frames, messages forwarded only to peers with matching subscribers |\n| **Gossip discovery** | PeerAnnounce/PeerList frames, new nodes need one seed address to join |\n| **mTLS** | rustls + tokio-rustls, P-256 certificates, WebPkiClientVerifier for both sides |\n| **Compression** | zstd level 1 for payloads above 256 bytes, capability-negotiated, output capped at 1 MB |\n| **Heartbeat** | 5s ping interval, 15s timeout, dead peer detection |\n| **Circuit breaker** | 10 failures to open, 60s reset, 3 half-open probe calls |\n| **Dead letter queue** | 1000-entry ring buffer for failed cluster sends |\n| **Presence sync** | PresenceUpdate/PresenceFull frames, CRDT last-write-wins conflict resolution |\n\n### Presence Tracking\n\n| Feature | Details |\n|---------|---------|\n| **Per-topic tracking** | Which users are active in each topic, with custom metadata (status, avatar, etc.) |\n| **User-level grouping** | Multiple connections from same JWT `sub` share one presence entry |\n| **Join/leave lifecycle** | `presence_join` on first connection, `presence_leave` on last disconnect |\n| **O(1) stats** | `presence_stats()` returns member/connection counts without iteration |\n| **Data updates** | `update_presence()` broadcasts to all topics where the user is present |\n| **Cluster sync** | Synchronized across all nodes, CRDT last-write-wins resolution |\n| **TTL sweep** | Background task every 30s removes entries from dead connections |\n\n### Message Recovery\n\n| Feature | Details |\n|---------|---------|\n| **Ring buffers** | Per-topic, power-of-2 capacity, bitmask indexing (single AND instruction) |\n| **Epoch+offset tracking** | Precise recovery positioning, epoch changes on buffer recreation |\n| **Memory management** | Global budget (default 256 MB), TTL eviction, LRU eviction when over budget |\n| **Zero-copy storage** | Recovery entries share `Bytes` (Arc) with the broadcast path |\n| **Recovery on reconnect** | `subscribe_with_recovery()` replays missed messages automatically |\n\n### Client SDKs (Python + TypeScript/React)\n\n| Feature | Details |\n|---------|---------|\n| **Auto-reconnection** | 4 strategies: exponential, linear, fibonacci, adaptive backoff with jitter |\n| **Connection pool** | Multi-endpoint with health scoring, 3 load balancing strategies, automatic failover |\n| **Circuit breaker** | CLOSED/OPEN/HALF_OPEN state machine, prevents connection storms |\n| **Rate limiting** | Client-side token bucket, coordinates with server feedback |\n| **E2E encryption** | Wire-compatible AES-GCM-256 + ECDH P-256 (both clients speak the same protocol) |\n| **Event sequencing** | Duplicate detection (sliding window) + out-of-order buffering |\n| **Network monitor** | Real-time latency, jitter, packet loss measurement, quality scoring |\n| **Priority queues** | 5 levels from CRITICAL to BACKGROUND |\n| **Offline queue** | IndexedDB persistence (TypeScript), replayed on reconnect |\n| **Compression** | Automatic zlib for messages above threshold |\n| **MessagePack** | Binary encoding for smaller payloads and faster serialization |\n| **Message signing** | HMAC-SHA256 integrity verification |\n\n### Transport Security\n\n| Feature | Details |\n|---------|---------|\n| **Origin validation** | Configure in reverse proxy (nginx/Caddy) to prevent CSWSH |\n| **Cookie auth** | `access_token` HTTP-only cookie with `Secure + SameSite=Lax` (OWASP recommended for browsers) |\n| **Frame protection** | 1 MB max frame size, serde_json parsing (no eval), escaped user IDs in server_ready |\n| **Cluster frame protection** | zstd decompression output capped at 1 MB (MAX_FRAME_SIZE), protocol version validation |\n\n---\n\n## Quick Start\n\n```bash\npip install wse-server\n```\n\n```python\nfrom wse_server import RustWSEServer, rust_jwt_encode\nimport time, threading\n\nserver = RustWSEServer(\n    \"0.0.0.0\", 5007,\n    max_connections=10_000,\n    jwt_secret=b\"replace-with-a-strong-secret-key!\",\n    jwt_issuer=\"my-app\",\n    jwt_audience=\"my-api\",\n)\nserver.enable_drain_mode()\nserver.start()\n\ndef handle_events(srv):\n    while True:\n        for ev in srv.drain_inbound(256, 50):\n            if ev[0] == \"auth_connect\":\n                srv.subscribe_connection(ev[1], [\"updates\"])\n            elif ev[0] == \"msg\":\n                print(f\"Message from {ev[1]}: {ev[2]}\")\n            elif ev[0] == \"disconnect\":\n                print(f\"Disconnected: {ev[1]}\")\n\nthreading.Thread(target=handle_events, args=(server,), daemon=True).start()\n\nwhile server.is_running():\n    time.sleep(1)\n```\n\nGenerate a test token:\n\n```python\ntoken = rust_jwt_encode(\n    {\"sub\": \"user-1\", \"iss\": \"my-app\", \"aud\": \"my-api\",\n     \"exp\": int(time.time()) + 3600, \"iat\": int(time.time())},\n    b\"replace-with-a-strong-secret-key!\",\n)\n```\n\n---\n\n## Server Configuration\n\n`RustWSEServer` constructor parameters:\n\n| Parameter | Default | Description |\n|-----------|---------|-------------|\n| `host` | required | Bind address |\n| `port` | required | Bind port |\n| `max_connections` | 1000 | Maximum concurrent WebSocket connections |\n| `jwt_secret` | None | JWT key for validation. HS256: shared secret (bytes, min 32). RS256/ES256: PEM public key. `None` disables auth |\n| `jwt_issuer` | None | Expected `iss` claim. Skipped if `None` |\n| `jwt_audience` | None | Expected `aud` claim. Skipped if `None` |\n| `jwt_cookie_name` | \"access_token\" | Cookie name for JWT token extraction |\n| `jwt_previous_secret` | None | Previous key for zero-downtime rotation. HS256: previous secret. RS256/ES256: previous public key PEM |\n| `jwt_key_id` | None | Expected `kid` header claim. Rejects tokens with mismatched key ID |\n| `jwt_algorithm` | None | JWT algorithm: `\"HS256\"` (default), `\"RS256\"`, or `\"ES256\"` |\n| `jwt_private_key` | None | PEM private key for RS256/ES256 token encoding. Not needed for HS256 |\n| `max_inbound_queue_size` | 131072 | Drain mode bounded queue capacity |\n| `recovery_enabled` | False | Enable per-topic message recovery buffers |\n| `recovery_buffer_size` | 128 | Ring buffer slots per topic (rounded to power-of-2) |\n| `recovery_ttl` | 300 | Buffer TTL in seconds before eviction |\n| `recovery_max_messages` | 500 | Max messages returned per recovery response |\n| `recovery_memory_budget` | 268435456 | Global memory limit for all recovery buffers (bytes, default 256 MB) |\n| `presence_enabled` | False | Enable per-topic presence tracking |\n| `presence_max_data_size` | 4096 | Max bytes for a user's presence metadata |\n| `presence_max_members` | 0 | Max tracked members per topic (0 = unlimited) |\n| `max_outbound_queue_bytes` | 16777216 | Per-connection outbound buffer limit (bytes, default 16 MB). Messages dropped when exceeded |\n| `rate_limit_capacity` | 100000.0 | Token bucket capacity per connection |\n| `rate_limit_refill` | 10000.0 | Token bucket refill rate per second |\n| `max_message_size` | 1048576 | Maximum WebSocket frame size in bytes (default 1 MB) |\n| `ping_interval` | 25 | Server-initiated ping interval in seconds |\n| `idle_timeout` | 60 | Force-close connections idle for this many seconds |\n\n---\n\n## API Reference\n\n### Lifecycle\n\n```python\nserver.start()                          # Start the server\nserver.stop()                           # Graceful shutdown\nserver.is_running()                     # Check server status (bool)\n```\n\n### Event Handling\n\n**Drain mode** (recommended) - events are queued in a lock-free crossbeam channel. Python polls in batches, acquiring the GIL once per batch.\n\n```python\nserver.enable_drain_mode()              # Switch to batch-polling mode (call before start)\nevents = server.drain_inbound(256, 50)  # Poll up to 256 events, wait up to 50ms\n```\n\nEach event is a tuple: `(event_type, conn_id, payload)`\n\n| Event Type | Trigger | Payload |\n|------------|---------|---------|\n| `\"auth_connect\"` | JWT-validated connection | user_id (string) |\n| `\"connect\"` | Connection without JWT | cookies (string) |\n| `\"msg\"` | Client sent WSE-prefixed JSON | parsed dict |\n| `\"raw\"` | Client sent plain text | raw string |\n| `\"bin\"` | Client sent binary frame | bytes |\n| `\"disconnect\"` | Connection closed | None |\n| `\"presence_join\"` | User's first connection joined a topic | dict with user_id, topic, data |\n| `\"presence_leave\"` | User's last connection left a topic | dict with user_id, topic, data |\n\n**Callback mode** - alternative to drain mode. Callbacks are invoked via `spawn_blocking` per event.\n\n```python\nserver.set_callbacks(on_connect, on_message, on_disconnect)\n```\n\n### Sending Messages\n\n```python\nserver.send(conn_id, text)                      # Send text to one connection\nserver.send_bytes(conn_id, data)                 # Send binary to one connection\nserver.send_event(conn_id, event_dict)           # Send structured event (auto-serialized, deduped, rate-checked)\n\nserver.broadcast_all(text)                       # Send to every connected client (text)\nserver.broadcast_all_bytes(data)                 # Send to every connected client (binary)\nserver.broadcast_local(topic, text)              # Fan-out to topic subscribers on this instance\nserver.broadcast(topic, text)                    # Fan-out to topic subscribers across all cluster nodes\n```\n\n| Method | Scope | Notes |\n|--------|-------|-------|\n| `send` | Single connection | Raw text frame |\n| `send_bytes` | Single connection | Raw binary frame |\n| `send_event` | Single connection | JSON-serialized, compressed if above threshold, deduplication via 50K-entry FIFO window |\n| `broadcast_all` | All connections | Pre-framed, single frame build shared via Arc |\n| `broadcast_local` | Topic (local) | Pre-framed, DashMap subscriber lookup, stored in recovery buffer if enabled |\n| `broadcast` | Topic (all nodes) | Local fan-out + forwarded to cluster peers with matching interest |\n\n### Topic Subscriptions\n\n```python\nserver.subscribe_connection(conn_id, [\"prices\", \"news\"])              # Subscribe to topics\nserver.subscribe_connection(conn_id, [\"chat\"], {\"status\": \"online\"})  # Subscribe with presence data\nserver.unsubscribe_connection(conn_id, [\"news\"])                      # Unsubscribe from specific topics\nserver.unsubscribe_connection(conn_id, None)                          # Unsubscribe from all topics\nserver.get_topic_subscriber_count(\"prices\")                           # Subscriber count for a topic\n```\n\nSubscriptions are cleaned up automatically on disconnect. In cluster mode, interest changes are propagated to peers via SUB/UNSUB frames.\n\n### Presence Tracking\n\nRequires `presence_enabled=True` in the constructor.\n\n```python\n# Query members in a topic\nmembers = server.presence(\"chat-room\")\n# {\"alice\": {\"data\": {\"status\": \"online\"}, \"connections\": 2},\n#  \"bob\":   {\"data\": {\"status\": \"away\"},   \"connections\": 1}}\n\n# Lightweight counts (O(1), no iteration)\nstats = server.presence_stats(\"chat-room\")\n# {\"num_users\": 2, \"num_connections\": 3}\n\n# Update a user's presence data across all their subscribed topics\nserver.update_presence(conn_id, {\"status\": \"away\"})\n```\n\nPresence is tracked at the user level (JWT `sub` claim). Multiple connections from the same user share a single presence entry. `presence_join` fires on first connection, `presence_leave` on last disconnect. In cluster mode, presence state is synchronized across all nodes using CRDT last-write-wins resolution.\n\n### Message Recovery\n\nRequires `recovery_enabled=True` in the constructor.\n\n```python\nresult = server.subscribe_with_recovery(\n    conn_id, [\"prices\"],\n    recover=True,\n    epoch=client_epoch,       # From previous session\n    offset=client_offset,     # From previous session\n)\n# {\"topics\": {\"prices\": {\"epoch\": 123, \"offset\": 456, \"recovered\": True, \"count\": 12}}}\n```\n\nThe server maintains per-topic ring buffers (power-of-2 capacity, bitmask indexing). Clients store the `epoch` and `offset` from their last received message. On reconnect, the server replays missed messages from the ring buffer. If the gap is too large or the epoch has changed, the client receives a `NotRecovered` status and should re-subscribe from scratch.\n\nMemory is managed with a global budget (default 256 MB), TTL eviction for idle buffers, and LRU eviction when over budget.\n\n### Cluster\n\n```python\n# Join a cluster mesh with mTLS\nserver.connect_cluster(\n    peers=[\"10.0.0.2:9999\", \"10.0.0.3:9999\"],\n    tls_ca=\"/etc/wse/ca.pem\",\n    tls_cert=\"/etc/wse/node.pem\",\n    tls_key=\"/etc/wse/node.key\",\n    cluster_port=9999,\n)\n\n# With gossip discovery (only seed addresses needed)\nserver.connect_cluster(\n    peers=[],\n    seeds=[\"10.0.0.2:9999\"],\n    cluster_addr=\"10.0.0.1:9999\",\n    cluster_port=9999,\n)\n\nserver.cluster_connected()       # True if connected to at least one peer\nserver.cluster_peers_count()     # Number of active peer connections\n```\n\nNodes form a full TCP mesh automatically. The cluster protocol uses a custom binary frame format with an 8-byte header, 12 message types, and capability negotiation during handshake. Features:\n\n- **Interest-based routing** - SUB/UNSUB/RESYNC frames. Messages are only forwarded to peers with matching subscribers.\n- **Gossip discovery** - PeerAnnounce/PeerList frames. New nodes need one seed address to join.\n- **mTLS** - mutual TLS via rustls with P-256 certificates and WebPkiClientVerifier.\n- **zstd compression** - payloads above 256 bytes compressed at level 1, capability-negotiated.\n- **Circuit breaker** - 10 failures to open, 60s reset, 3 half-open probe calls.\n- **Heartbeat** - 5s interval, 15s timeout, dead peer detection.\n- **Dead letter queue** - 1000-entry ring buffer for failed cluster sends.\n- **Presence sync** - PresenceUpdate/PresenceFull frames with CRDT conflict resolution.\n\n### Health Monitoring\n\n```python\nhealth = server.health_snapshot()\n# {\n#     \"connections\": 150,\n#     \"inbound_queue_depth\": 0,\n#     \"inbound_dropped\": 0,\n#     \"uptime_secs\": 3600.5,\n#     \"recovery_enabled\": True,\n#     \"recovery_topic_count\": 5,\n#     \"recovery_total_bytes\": 1048576,\n#     \"cluster_connected\": True,\n#     \"cluster_peer_count\": 2,\n#     \"cluster_messages_sent\": 50000,\n#     \"cluster_messages_delivered\": 49950,\n#     \"cluster_messages_dropped\": 0,\n#     \"cluster_bytes_sent\": 1048576,\n#     \"cluster_bytes_received\": 1024000,\n#     \"cluster_reconnect_count\": 0,\n#     \"cluster_unknown_message_types\": 0,\n#     \"cluster_dlq_size\": 0,\n#     \"presence_enabled\": True,\n#     \"presence_topics\": 3,\n#     \"presence_total_users\": 25,\n# }\n```\n\n### Connection Management\n\n```python\nserver.get_connection_count()        # Lock-free AtomicUsize read\nserver.get_connections()             # List all connection IDs (snapshot)\nserver.disconnect(conn_id)           # Force-disconnect a connection\nserver.inbound_queue_depth()         # Events waiting to be drained\nserver.inbound_dropped_count()       # Events dropped due to full queue\nserver.get_cluster_dlq_entries()     # Retrieve failed cluster messages from dead letter queue\n```\n\n---\n\n## Security\n\n### JWT Authentication\n\nRust-native HS256 validation during the WebSocket handshake. Zero GIL acquisition, 0.01ms per decode.\n\nToken delivery:\n- **Browser clients**: `access_token` HTTP-only cookie (set by your login endpoint, attached automatically by the browser)\n- **Backend clients**: `Authorization: Bearer \u003ctoken\u003e` header and/or `access_token` cookie\n- **API clients**: `Authorization: Bearer \u003ctoken\u003e` header\n\nRequired claims: `sub` (user ID), `exp` (expiration). Recommended: `iat` (issued at). Optional: `iss`, `aud` (validated if configured).\n\n### End-to-End Encryption\n\nPer-connection session keys via ECDH P-256 key exchange, AES-GCM-256 encryption, HKDF-SHA256 key derivation.\n\nWire format: `E:` prefix + 12-byte IV + AES-GCM ciphertext + 16-byte auth tag.\n\nEnable on the client side - the server handles key exchange automatically during the handshake.\n\n### Rate Limiting\n\nPer-connection token bucket: 100,000 token capacity, 10,000 tokens/second refill. Clients receive a `rate_limit_warning` at 20% remaining capacity, and `RATE_LIMITED` error when exceeded.\n\n### Deduplication\n\n`send_event()` maintains a 50,000-entry AHashSet with FIFO eviction. Duplicate message IDs are dropped before serialization.\n\n### Zombie Detection\n\nServer pings every connected client every 25 seconds. Connections with no activity for 60 seconds are force-closed.\n\nFull security documentation: [docs/SECURITY.md](docs/SECURITY.md)\n\n---\n\n## Wire Protocol\n\nWSE uses a custom wire protocol with categorized JSON messages:\n\n**Text frames:** JSON with `c` field for category: `\"WSE\"` (system), `\"S\"` (snapshot), `\"U\"` (update)\n\n**Binary frames:** `C:` (zlib compressed), `M:` (MessagePack), `E:` (AES-GCM encrypted), raw zlib (0x78 magic byte)\n\n**MessagePack transport:** opt-in per connection via `?format=msgpack` query parameter. Roughly 2x faster serialization and 30% smaller payloads.\n\n**Protocol negotiation:** `client_hello`/`server_hello` handshake with feature discovery, capability advertisement, and version agreement.\n\nFull protocol specification: [docs/PROTOCOL.md](docs/PROTOCOL.md)\n\n---\n\n## Compression\n\nTwo compression layers:\n\n- **Client-facing:** zlib for messages above the configurable threshold (default 1024 bytes). Applied automatically by `send_event()`.\n- **Inter-peer (cluster):** zstd level 1 for payloads above 256 bytes. Capability-negotiated during handshake. Decompression output capped at 1 MB (MAX_FRAME_SIZE).\n\n---\n\n## Client SDKs\n\n### Python\n\n```bash\npip install wse-client\n```\n\nFull-featured async and sync client with connection pool, circuit breaker, auto-reconnect, E2E encryption, and msgpack binary transport.\n\n```python\nfrom wse_client import connect\n\nasync with connect(\"ws://localhost:5007/wse\", token=\"\u003cjwt\u003e\") as client:\n    await client.subscribe([\"updates\"])\n    async for event in client:\n        print(event.type, event.payload)\n```\n\n**Sync interface:**\n\n```python\nfrom wse_client import SyncWSEClient\n\nclient = SyncWSEClient(\"ws://localhost:5007/wse\", token=\"\u003cjwt\u003e\")\nclient.connect()\nclient.subscribe([\"updates\"])\n\n@client.on(\"updates\")\ndef handle(event):\n    print(event.payload)\n\nclient.run_forever()\n```\n\nKey features: 4 reconnect strategies (exponential, linear, fibonacci, adaptive), connection pool with health scoring and 3 load balancing strategies, circuit breaker, token bucket rate limiter, event sequencer with dedup and reorder buffering, network quality monitoring (latency/jitter/packet loss).\n\nSee [python-client/](python-client/) for full source and examples.\n\n### TypeScript / React\n\n```bash\nnpm install wse-client\n```\n\nSingle React hook (`useWSE`) for connection lifecycle, subscriptions, and message dispatch.\n\n```tsx\nimport { useWSE } from 'wse-client';\n\nfunction App() {\n  const { sendMessage, connectionHealth } = useWSE(\n    '\u003cjwt-token\u003e',\n    ['updates'],\n    { endpoints: ['ws://localhost:5007/wse'] },\n  );\n\n  return \u003cdiv\u003eStatus: {connectionHealth}\u003c/div\u003e;\n}\n```\n\nKey features: offline queue with IndexedDB persistence, adaptive quality management, connection pool with health scoring, E2E encryption (Web Crypto API), message batching, 5 priority levels, Zustand store for external state access.\n\nSee [client/](client/) for full source and examples.\n\n---\n\n## Performance\n\nBenchmarked on AMD EPYC 7502P (32 cores / 64 threads, 128 GB RAM), Ubuntu 24.04.\n\n| Mode | Peak Throughput | Connections | Message Loss |\n|------|----------------|-------------|--------------|\n| Standalone (fan-out) | 4.7M deliveries/s | 100K | 0% |\n| Standalone (inbound JSON) | 14.7M msg/s | 500K | 0% |\n| Standalone (inbound msgpack) | 30M msg/s | 500K | 0% |\n| Cluster (2 nodes, 50/50) | 6.6M deliveries/s | 500 per node | 0% |\n\nSub-millisecond latency. Median 0.38ms with JWT authentication. Connection handshake: 0.53ms median (Rust JWT path).\n\nDetailed results: [Benchmarks](docs/BENCHMARKS.md) | [Fan-out](docs/BENCHMARKS_FANOUT.md) | [Rust Client](docs/BENCHMARKS_RUST_CLIENT.md) | [Python Client](docs/BENCHMARKS_PYTHON_CLIENT.md) | [TypeScript Client](docs/BENCHMARKS_TS_CLIENT.md)\n\n---\n\n## Examples\n\nWorking examples in the [`examples/`](examples/) directory:\n\n| Example | Description |\n|---------|-------------|\n| [`standalone_basic.py`](examples/standalone_basic.py) | Basic server with JWT auth and echo |\n| [`standalone_broadcast.py`](examples/standalone_broadcast.py) | Topic-based pub/sub with broadcasting |\n| [`standalone_presence.py`](examples/standalone_presence.py) | Per-topic presence tracking with join/leave events |\n| [`standalone_recovery.py`](examples/standalone_recovery.py) | Message recovery on reconnect with epoch+offset |\n\n---\n\n## Documentation\n\n- [Architecture](docs/ARCHITECTURE.md) - server internals, PyO3 bridge, concurrency model\n- [Integration Guide](docs/INTEGRATION.md) - complete setup and API reference\n- [Wire Protocol](docs/PROTOCOL.md) - message format specification\n- [Cluster Protocol](docs/CLUSTER_PROTOCOL.md) - TCP mesh, frame format, gossip, interest routing\n- [Rust Utilities](docs/RUST_UTILITIES.md) - priority queues, rate limiters, sequencing, compression, crypto, JWT\n- [Security](docs/SECURITY.md) - JWT, encryption, mTLS, rate limiting, circuit breaker\n- [Deployment](docs/DEPLOYMENT.md) - production setup, Docker, Kubernetes, cluster configuration\n- [Migration Guide](docs/MIGRATION.md) - upgrading from v1.x to v2.0\n- [Contributing](CONTRIBUTING.md) - development setup and coding standards\n- [Changelog](CHANGELOG.md) - version history\n\n---\n\n## License\n\nMIT\n","funding_links":["https://github.com/sponsors/silvermpx"],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsilvermpx%2Fwse","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsilvermpx%2Fwse","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsilvermpx%2Fwse/lists"}