Skip to content

Production Deployment

This guide covers deploying the Protean server in production — process management, containerization, scaling strategies, and health checks.

For basic server usage, see Run the Server.

Process Management

Use a process manager like systemd, supervisord, or Docker:

# /etc/systemd/system/protean-server.service
[Unit]
Description=Protean Message Server
After=network.target

[Service]
Type=simple
User=app
WorkingDirectory=/app
Environment=PROTEAN_ENV=production
ExecStart=/app/.venv/bin/protean server --domain=my_domain
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target

Docker

FROM python:3.11-slim

WORKDIR /app
COPY . .
RUN pip install poetry && poetry install

ENV PROTEAN_ENV=production
CMD ["poetry", "run", "protean", "server", "--domain=my_domain"]

Kubernetes

apiVersion: apps/v1
kind: Deployment
metadata:
  name: protean-server
spec:
  replicas: 3  # Multiple workers for scaling
  selector:
    matchLabels:
      app: protean-server
  template:
    metadata:
      labels:
        app: protean-server
    spec:
      containers:
      - name: server
        image: my-app:latest
        command: ["protean", "server", "--domain=my_domain"]
        env:
        - name: PROTEAN_ENV
          value: "production"
        resources:
          requests:
            memory: "256Mi"
            cpu: "250m"
          limits:
            memory: "512Mi"
            cpu: "500m"

Scaling Considerations

StreamSubscription supports horizontal scaling:

  • Multiple server instances can run concurrently
  • Messages are distributed across consumers via Redis consumer groups
  • Each message is processed by exactly one consumer

EventStoreSubscription has limited scaling:

  • Multiple instances will process the same messages
  • Use for projections where idempotency is guaranteed
  • Consider using StreamSubscription for scalable workloads

Health Checks

Add health checks for production deployments:

# health_check.py
import sys
from my_domain import domain

def check_health():
    try:
        # Verify domain can activate
        with domain.domain_context():
            # Check broker connectivity
            broker = domain.brokers.get("default")
            if broker:
                broker.ping()  # If supported

            # Check event store connectivity
            if domain.event_store:
                domain.event_store.store.ping()  # If supported

        return 0
    except Exception as e:
        print(f"Health check failed: {e}")
        return 1

if __name__ == "__main__":
    sys.exit(check_health())