Deployment

This page summarizes common deployment patterns for ActingWeb apps.

Docker

# Dockerfile
FROM python:3.11-slim
WORKDIR /app
COPY pyproject.toml poetry.lock ./
RUN pip install poetry && poetry config virtualenvs.create false \
    && poetry install --only main --no-root
COPY . .
CMD ["python", "app.py"]
  • Expose the port your Flask/FastAPI app listens on (e.g., 5000).

  • Pass configuration via environment (e.g., APP_HOST_FQDN, LOG_LEVEL).

AWS Lambda (Serverless)

# handler.py
import serverless_wsgi
from flask import Flask
from actingweb.interface import ActingWebApp

flask_app = Flask(__name__)
aw_app = (
    ActingWebApp(...)
    .with_web_ui()
    .with_sync_callbacks()  # IMPORTANT for Lambda!
)
aw_app.integrate_flask(flask_app)

def handler(event, context):
    return serverless_wsgi.handle_request(flask_app, event, context)

Important: Enable Synchronous Callbacks

In Lambda/serverless environments, async fire-and-forget callbacks may be lost when the function freezes after returning a response. Use with_sync_callbacks() to ensure all subscription callbacks (both diff and resync) complete before the handler returns:

aw_app = ActingWebApp(...).with_sync_callbacks(enable=True)

This makes callbacks use blocking HTTP requests instead of async tasks, guaranteeing delivery at the cost of slightly longer response times.

Why this is needed:

  • Lambda freezes execution after returning a response

  • Async fire-and-forget callbacks are terminated before completion

  • Sync callbacks block until delivery is confirmed

  • Both diff callbacks and resync callbacks respect this configuration

Local Development:

Do NOT use with_sync_callbacks() in local/container deployments:

  • Default async behavior prevents blocking and self-deadlock

  • Async mode allows both actors on the same server to communicate without blocking

  • Callbacks complete in the background after the response is returned

Note

ActingWeb automatically detects Lambda environments (via AWS_LAMBDA_FUNCTION_NAME or AWS_EXECUTION_ENV environment variables) and logs a warning if sync callbacks are not enabled. This helps catch misconfigurations during development and deployment.

Serverless config example:

service: actingweb-app
provider:
  name: aws
  runtime: python3.11
  region: us-east-1
functions:
  app:
    handler: handler.handler
    events:
      - http:
          path: /{proxy+}
          method: ANY
      - http:
          path: /
          method: ANY

Kubernetes

apiVersion: apps/v1
kind: Deployment
metadata:
  name: actingweb-app
spec:
  replicas: 2
  selector:
    matchLabels:
      app: actingweb-app
  template:
    metadata:
      labels:
        app: actingweb-app
    spec:
      containers:
      - name: actingweb
        image: your-registry/actingweb:latest
        ports:
        - containerPort: 5000

Notes

  • Ensure AWS IAM policies allow DynamoDB operations your app requires.

  • For base paths (reverse proxies, API gateways), templates should use actor_root and actor_www; see WWW Handler and Templates.

  • See Routing Overview for generated routes and structure.

Health Checks

  • Simple Flask health endpoint:

    @app.route("/health")
    def health():
        return {"status": "ok"}, 200
    
  • Simple FastAPI health endpoint:

    @api.get("/health")
    def health():
        return {"status": "ok"}
    

Base Path (Reverse Proxy) Examples

FastAPI (root_path)

# Deploying under /mcp-server
api = FastAPI(root_path="/mcp-server")
aw.integrate_fastapi(api, templates_dir="templates")

Nginx

server {
  listen 443 ssl;
  server_name your.domain;

  location /mcp-server/ {
    proxy_pass http://127.0.0.1:5000/;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Forwarded-Prefix /mcp-server;
  }
}

Notes on Base Paths

  • When running under a base path, ensure links in templates use actor_root and actor_www (not relative URLs).

  • For FastAPI, prefer root_path so OpenAPI and routes align with the proxy path.

  • For Flask, when using WSGI behind a proxy that sets X-Forwarded-Prefix/SCRIPT_NAME, make sure the WSGI server/middleware honors it (e.g., werkzeug.middleware.proxy_fix.ProxyFix if needed).