Deployment Guide
This guide covers running Statewave in different environments.
1. Local Development (Docker Compose)
The fastest way to run Statewave locally.
Prerequisites
- Docker & Docker Compose
- Git
Steps
bash
git clone https://github.com/smaramwbc/statewave.git
cd statewave
# Copy and optionally edit environment config
cp .env.example .env
# Start Postgres + API
docker compose up -d
# Run migrations
docker compose exec api alembic upgrade head
# Verify
curl http://localhost:8100/healthz```
The API is available at `http://localhost:8100`. Postgres data persists in the `pgdata` volume.
### Useful commands
```bash
docker compose logs -f api # tail API logs
docker compose down # stop services
docker compose down -v # stop + delete data2. Local Development (bare metal)
Run without Docker — useful for debugging or IDE integration.
Prerequisites
- Python 3.11+
- PostgreSQL 16 with pgvector extension
- Git
Steps
bash
git clone https://github.com/smaramwbc/statewave.git
cd statewave
# Create and activate venv
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
# Start Postgres (or use docker compose up db -d for just the database)
# Ensure pgvector extension is installed:
# CREATE EXTENSION IF NOT EXISTS vector;
# Set connection string
export STATEWAVE_DATABASE_URL=postgresql+asyncpg://statewave:statewave@localhost:5432/statewave
# Run migrations
alembic upgrade head
# Start server
uvicorn server.app:app --reload --port 81003. Single Container Deployment
Deploy Statewave as a single container pointing to an external Postgres.
bash
docker build -t statewave .
docker run -d \
--name statewave \
-p 8100:8100 \
-e STATEWAVE_DATABASE_URL=postgresql+asyncpg://user:pass@your-db-host:5432/statewave \
-e STATEWAVE_DEBUG=false \
-e STATEWAVE_API_KEY=your-secret-key \
statewaveRun migrations against the remote database before first start:
bash
docker run --rm \
-e STATEWAVE_DATABASE_URL=postgresql+asyncpg://user:pass@your-db-host:5432/statewave \
statewave \
alembic upgrade head4. Fly.io
Prerequisites
flyctlCLI installed and authenticated- A Fly Postgres cluster (or external Postgres)
Steps
bash
cd statewave
# Create app
fly launch --no-deploy
# Set secrets
fly secrets set \
STATEWAVE_DATABASE_URL=postgresql+asyncpg://user:pass@your-fly-db.internal:5432/statewave \
STATEWAVE_API_KEY=your-secret-key
# Deploy
fly deploy
# Run migrations (one-off machine)
fly machine run . --command "alembic upgrade head" --rmA minimal fly.toml:
toml
[http_service]
internal_port = 8100
force_https = true
[env]
STATEWAVE_HOST = "0.0.0.0"
STATEWAVE_PORT = "8100"
STATEWAVE_DEBUG = "false"5. Railway
Steps
- Connect your
statewaverepo to Railway - Add a Postgres service (Railway provisions pgvector-capable Postgres)
- Set environment variables:
STATEWAVE_DATABASE_URL→ Railway providesDATABASE_URL; convert to asyncpg format: replacepostgresql://withpostgresql+asyncpg://STATEWAVE_API_KEY→ your secretSTATEWAVE_DEBUG→false
- Set start command:
alembic upgrade head && uvicorn server.app:app --host 0.0.0.0 --port $PORT - Deploy
Environment Variables Reference
See .env.example for all available STATEWAVE_* configuration options.
Production Checklist
- [ ]
STATEWAVE_DEBUG=false - [ ]
STATEWAVE_API_KEYset to a strong secret - [ ]
STATEWAVE_CORS_ORIGINSrestricted to your domain(s) - [ ]
STATEWAVE_RATE_LIMIT_RPMset (e.g., 120) - [ ] Database backups configured
- [ ] Migrations run before first request
- [ ] Health endpoint monitored (
GET /healthz)
Admin Console (optional)
For operator visibility into your running Statewave instance, you can deploy the admin console.
See statewave-admin for setup instructions.
The admin console provides:
- System readiness and database health status
- Compile job monitoring
- Webhook delivery status
- Usage metering (episodes, memories, compiles)
- Subject health distribution
Important: The admin console is an internal tool. Deploy it behind an access gateway (Cloudflare Access, OAuth2 Proxy, etc.) — do not expose publicly.