Skip to content

Architecture

Understanding PyStrands' architecture helps you build scalable, resilient real-time applications.

Overview

PyStrands uses a three-tier architecture that separates concerns for scalability and reliability:

┌─────────────────┐     WebSocket     ┌─────────────────┐      TCP       ┌─────────────────┐
│                 │ ←──────────────→ │                 │ ←────────────→ │                 │
│  Web/Browser    │                   │   Go Broker     │                │ Python Backend  │
│    Clients      │                   │  (stateful)     │                │   (your code)   │
│                 │                   │                 │                │                 │
└─────────────────┘                   │  ┌───────────┐  │                └─────────────────┘
                                      │  │  Queue    │  │                ┌─────────────────┐
                                      │  │  [msg1]   │  │ ←────────────→ │ Python Backend  │
                                      │  │  [msg2]   │  │                │   (replica 2)   │
                                      │  │  [msg3]   │  │                └─────────────────┘
                                      │  └───────────┘  │
                                      └─────────────────┘

Components

1. WebSocket Clients

Clients connect to the Go broker via WebSocket. They can be: - Browser applications (JavaScript WebSocket API) - Mobile apps - IoT devices - Any WebSocket-capable client

Clients are identified by a unique client_id and can be organized into rooms for targeted messaging.

2. Go Broker

The Go broker is the heart of PyStrands. It handles:

  • WebSocket connections — Manages client connections and disconnections
  • Message routing — Routes messages between clients and Python backends
  • Room management — Maintains room state and membership
  • Message queuing — Buffers messages when backends are unavailable
  • Load balancing — Distributes work across multiple Python backends

Stateless Design

The Go broker is designed to be stateless relative to Python backends. Multiple broker instances can run behind a load balancer for horizontal scaling.

3. Python Backends

Your Python code connects to the Go broker via TCP and handles business logic:

  • Connection validation — Accept or reject incoming WebSocket connections
  • Message processing — Handle incoming messages and send responses
  • State management — Maintain application state (database, cache, etc.)

Python backends can scale horizontally — add more instances to handle increased load.

Message Flow

Connection Flow

1. Client → Go Broker: WebSocket upgrade request
2. Go Broker → Python Backend: connection_request message
3. Python Backend → Go Broker: accept/reject response
4. Go Broker → Client: WebSocket established (or rejected)
5. Go Broker → Python Backend: new_connection notification

Message Flow

1. Client A → Go Broker: "Hello!"
2. Go Broker → Python Backend: new_message with context
3. Python Backend processes message
4. Python Backend → Go Broker: send_room_message(room_id, "Echo: Hello!")
5. Go Broker → All clients in room: "Echo: Hello!"

Scaling

Horizontal Scaling Python Backends

Add more Python backend instances to handle increased load:

                    ┌─────────────────┐
                    │   Load Balancer │
                    │  (WebSocket)    │
                    └────────┬────────┘
                    ┌────────▼────────┐
                    │   Go Broker 1   │
                    │   Go Broker 2   │
                    └────────┬────────┘
              ┌──────────────┼──────────────┐
              │              │              │
       ┌──────▼──────┐ ┌─────▼──────┐ ┌─────▼──────┐
       │ Python      │ │ Python     │ │ Python     │
       │ Backend 1   │ │ Backend 2  │ │ Backend 3  │
       └─────────────┘ └────────────┘ └────────────┘

The Go broker load-balances connection requests and messages across all connected Python backends.

Message Queuing

When all Python backends disconnect, the Go broker can queue messages (if --queue-size > 0):

┌─────────────┐         ┌─────────────┐         ┌─────────────┐
│   Client    │ ──────→ │  Go Broker  │         │  No Python  │
│  (sending)  │         │  (queues    │    X    │  backends   │
│             │         │   message)  │         │  connected  │
└─────────────┘         └──────┬──────┘         └─────────────┘
                        (Python backend reconnects)
                        ┌─────────────┐
                        │  Go Broker  │ ──────→ │ Python      │
                        │  (flushes   │         │ Backend     │
                        │   queue)    │         │ (receives   │
                        └─────────────┘         │ queued msg) │
                                                └─────────────┘

Queue Limitations

The message queue is stored in memory. If the queue fills up or the broker restarts, queued messages are lost. For guaranteed delivery, implement application-level acknowledgments.

Protocol

TCP Protocol (Python ↔ Go)

Messages between Python backends and the Go broker use JSON over TCP, delimited by newlines:

{
    "action": "message_to_room",
    "request_id": "uuid-v4-string",
    "params": {
        "room_id": "room1",
        "message": "Hello, room!"
    }
}

Actions

From Python to Go:

Action Description
broadcast Send message to all connected clients
message_to_room Send message to all clients in a room
message_to_connection Send message to a specific client
response Response to a connection request

From Go to Python:

Action Description
connection_request New WebSocket client wants to connect
new_connection Client successfully connected
new_message Client sent a message
disconnected Client disconnected
error An error occurred
heartbeat Keep-alive ping from server

Deployment Patterns

Single Server

For development or small deployments:

┌─────────────────────────────────────┐
│           Single Server             │
│  ┌─────────┐    ┌───────────────┐   │
│  │ Go      │←──→│ Python        │   │
│  │ Broker  │    │ Backend       │   │
│  └────┬────┘    └───────────────┘   │
│       │                             │
│  [WebSocket Port 8080]              │
└───────┼─────────────────────────────┘
   [Browser Clients]

Multi-Backend Production

For production with high availability:

┌─────────────────┐
│  Load Balancer  │  (nginx, HAProxy, cloud LB)
│   (WebSocket)   │
└────────┬────────┘
    ┌────┴────┐
    ▼         ▼
┌───────┐ ┌───────┐
│ Go    │ │ Go    │
│Broker1│ │Broker2│
└───┬───┘ └───┬───┘
    │         │
    └────┬────┘
    ┌────┴────┐
    ▼         ▼
┌───────┐ ┌───────┐
│Python │ │Python │
│Backend│ │Backend│
│   1   │ │   2   │
└───────┘ └───────┘

Sticky Sessions

WebSocket connections require sticky sessions when using multiple Go brokers. Configure your load balancer accordingly.