Skip to content

Basic Concepts

Understanding the core concepts of RevenProx.

Server-Sent Events (SSE)

Server-Sent Events is a standard for pushing real-time updates from server to client over HTTP. Unlike WebSockets, SSE is:

  • Unidirectional: Server to client only
  • HTTP-based: Works through proxies and firewalls
  • Auto-reconnecting: Built-in reconnection with event IDs
  • Simple: No special protocol negotiation

SSE Message Format

event: message
id: 12345
data: {"type": "notification", "text": "Hello!"}

event: heartbeat
data: ping

Each message consists of: - event: Event type (optional, defaults to "message") - id: Unique identifier for reconnection - data: The payload (can span multiple lines) - Empty line terminates the message

Topics

Topics are named channels that clients subscribe to. Events are routed to all clients subscribed to a topic.

Topic: user-123-notifications
  ├── Client A (mobile app)
  ├── Client B (web browser)
  └── Client C (desktop app)

Topic UUIDs

Internally, topics are represented as 128-bit UUIDs for efficient routing:

Topic Name: "user-notifications"
Topic UUID: a1b2c3d4-e5f6-7890-abcd-ef1234567890

The UUID is derived from the topic name using a consistent hashing algorithm.

Connections

A connection represents a single SSE stream between a client and the proxy.

Connection Lifecycle

1. Client Request     → HTTP GET /events/{topic}
2. Authentication     → JWT verified via webhook
3. Connection Setup   → SSE stream established
4. Event Streaming    → Messages pushed to client
5. Keepalive          → Periodic heartbeats
6. Disconnection      → Client closes or timeout

Connection States

State Description
connecting Initial connection setup
active Receiving events
idle No recent activity
closing Graceful shutdown
closed Connection terminated

JWT Authentication

RevenProx uses webhook-based JWT verification for flexible authentication.

Authentication Flow

┌────────┐     1. GET /events/topic     ┌───────────┐
│ Client │ ─────────────────────────────► RevenProx │
└────────┘   Authorization: Bearer JWT   └─────┬─────┘
                                    2. POST /verify
                                         ┌─────▼─────┐
                                         │  Webhook  │
                                         │  Server   │
                                         └─────┬─────┘
                                    3. {valid: true}
┌────────┐     4. SSE Stream            ┌─────▼─────┐
│ Client │ ◄─────────────────────────── │ RevenProx │
└────────┘                               └───────────┘

JWT Caching

Verified tokens are cached to reduce webhook calls:

  • Cache key: SHA-256 hash of the JWT
  • TTL: Configurable (default 300 seconds)
  • Max size: Configurable with LRU eviction

Circuit Breaker

If the webhook fails repeatedly, the circuit breaker opens:

Closed (normal)  →  Open (failing)  →  Half-Open (testing)
     ▲                    │                    │
     └────────────────────┴────────────────────┘

Rate Limiting

RevenProx implements per-IP rate limiting to prevent abuse.

Token Bucket Algorithm

Each IP address has a token bucket:

  • Tokens replenish at a fixed rate
  • Each request consumes one token
  • Requests are rejected when bucket is empty
[http]
rate_limit_per_ip = 100      # requests per window
rate_limit_window_sec = 60   # window duration

Connection Pooling

The proxy manages connections efficiently using a connection pool.

Thread Pool

Worker threads handle client connections:

┌─────────────────────────────────────────┐
│              Thread Pool                │
├──────────┬──────────┬──────────────────┤
│ Worker 1 │ Worker 2 │    Worker N      │
│  ┌───┐   │  ┌───┐   │     ┌───┐       │
│  │ C │   │  │ C │   │     │ C │       │
│  └───┘   │  └───┘   │     └───┘       │
└──────────┴──────────┴──────────────────┘

Backpressure

When the queue is full, backpressure policies apply:

Policy Behavior
drop_newest Reject new messages
drop_oldest Remove oldest messages
block Wait for queue space

Distributed State

For horizontal scaling, multiple proxy instances synchronize state.

NNG Messaging

Proxies communicate using NNG (nanomsg-next-generation):

┌───────────┐     pub/sub     ┌───────────┐
│  Proxy A  │ ◄─────────────► │  Proxy B  │
└───────────┘                 └───────────┘
      ▲                             ▲
      │           pub/sub           │
      └──────────────┬──────────────┘
               ┌─────▼─────┐
               │  Proxy C  │
               └───────────┘

Subscription Sync

When a client subscribes on Proxy A:

  1. Proxy A records the subscription locally
  2. Proxy A broadcasts to peers via NNG
  3. Proxies B and C update their routing tables
  4. Events for that topic reach the client via any proxy

Bloom Filters

Efficient membership testing for subscriptions:

Topic in subscriptions?
┌─────────────────┐
│  Bloom Filter   │  → Maybe/No (fast)
└────────┬────────┘
         │ if Maybe
┌─────────────────┐
│  Hash Table     │  → Yes/No (accurate)
└─────────────────┘

Metrics

RevenProx exposes metrics for monitoring:

Metric Description
connections_active Current open connections
connections_total Total connections since start
messages_sent Total messages delivered
bytes_sent Total bytes transmitted
auth_cache_hits JWT cache hit count
auth_failures Authentication failures

Next Steps