Infrastructure Management

This guide covers the full lifecycle of Sagewai's infrastructure services: starting and stopping containers, monitoring health, managing data volumes, running database migrations, and running without containers when needed.

Service dependency graph

Services start in dependency order. If a dependency is not healthy, downstream services will not start correctly.

PostgreSQL (standalone)        Redis (standalone)

etcd ──► MinIO ──► Milvus

nebula-metad ──► nebula-storaged ──► nebula-graphd

OTel Collector ──► Loki ──► Grafana
                   Tempo ──► Grafana
Prometheus ──────────────► Grafana

PostgreSQL and Redis have no dependencies and start independently. Milvus requires etcd and MinIO to be healthy first. NebulaGraph services must start in order: metad, then storaged, then graphd. All observability data flows into Grafana.

Starting services

# Full stack (all services + observability)
make infra

# Core only (PostgreSQL + Redis, ~200 MB RAM)
make infra-core

# Full stack with containerized application backends
make dev-up

Stopping services

# Stop all containers, keep data volumes
make down
# equivalent to:
docker compose down

# Stop and delete all data volumes (fresh start)
docker compose down -v

Monitoring

# Check running containers and health status
docker compose ps

# Follow logs for one service
docker compose logs -f milvus

# Follow logs for all services
docker compose logs -f

# Check health endpoints
curl http://localhost:8000/api/v1/health/summary   # Admin API summary
curl http://localhost:8000/api/v1/health/detailed  # Detailed infrastructure health

Common operations

# Restart one service without rebuilding
docker compose restart milvus

# Rebuild and restart one service
docker compose up -d --build admin

# Scale workers horizontally
docker compose up -d --scale worker=3

# Check per-container resource usage
docker stats

Compose Specification compatibility

Sagewai's docker-compose.yml targets the Compose Specification, so it works with multiple container runtimes:

RuntimeCommandNotes
Docker Compose V2docker compose up -dDefault on modern Docker Desktop
Podman Composepodman-compose up -dDrop-in replacement
nerdctl (containerd)nerdctl compose up -dLightweight alternative

The version: field is optional in the Compose Spec and may be omitted.

Podman alternative

Podman is a rootless, daemonless runtime that works as a drop-in replacement for Docker.

Install:

# macOS
brew install podman podman-compose
podman machine init
podman machine start

# Linux (Ubuntu/Debian)
sudo apt install podman podman-compose

# Alias for Makefile compatibility
alias docker=podman
alias docker-compose=podman-compose

Key differences from Docker:

FeatureDockerPodman
DaemonRequires dockerdDaemonless
Root accessRoot by defaultRootless by default
Socket/var/run/docker.sockUser-level socket
Composedocker composepodman-compose
GPU support--gpus all--device nvidia.com/gpu=all

Start Sagewai with Podman:

podman-compose -f docker-compose.yml up -d

# With the alias set above, Makefile targets work unchanged:
make infra

Volume permissions: Podman runs rootless by default. If you are on SELinux, add the :Z suffix to volume mounts:

volumes:
  - ./data:/var/lib/postgresql/data:Z

Native setup (no containers)

Use this when containers are not available or not practical.

PostgreSQL

# macOS
brew install postgresql@15
brew services start postgresql@15
createdb sagewai

# Ubuntu/Debian
sudo apt install postgresql-15
sudo -u postgres createdb sagewai

Set the connection string:

export DATABASE_URL=postgresql://localhost:5432/sagewai

Redis

# macOS
brew install redis
brew services start redis

# Ubuntu/Debian
sudo apt install redis-server
sudo systemctl start redis
export REDIS_URL=redis://localhost:6379

Milvus (optional)

Required for vector search. Without it, Sagewai falls back to in-memory vectors, which is fine for development.

Option A: Standalone binary

curl -sfL https://raw.githubusercontent.com/milvus-io/milvus/master/scripts/standalone_embed.sh | bash

Option B: Zilliz Cloud (managed)

Sign up at cloud.zilliz.com and set:

export MILVUS_HOST=your-cluster.zillizcloud.com
export MILVUS_PORT=19530

NebulaGraph (optional)

Required for knowledge graphs. Without it, Sagewai falls back to in-memory graphs, which is sufficient for development. Download from nebula-graph.io.

Data volume management

Where data lives

ServiceVolume nameContents
PostgreSQLsagewai_postgres_dataWorkflows, runs, workers, audit logs
Milvussagewai_milvus_dataVector embeddings
MinIOsagewai_minio_dataMilvus object storage
etcdsagewai_etcd_dataMilvus metadata
NebulaGraphsagewai_nebula_*Graph data and metadata
RedisIn-memoryCache only (no persistence by default)

Backup

# Plain SQL dump
docker compose exec postgres pg_dump -U sagewai sagewai > backup.sql

# Compressed custom-format dump
docker compose exec postgres pg_dump -U sagewai -Fc sagewai > backup.dump

Restore

# From plain SQL dump
docker compose exec -T postgres psql -U sagewai sagewai < backup.sql

# From compressed dump
docker compose exec -T postgres pg_restore -U sagewai -d sagewai < backup.dump

Full reset

docker compose down -v
make infra
make db-upgrade
make db-seed  # optional: load demo data

Or use the combined shortcut:

make db-fresh  # drop + migrate + seed in one command

Database migrations

Migrations are managed by Alembic. Migration files live in sagewai/db/migrations/versions/.

# Apply pending migrations
make db-upgrade

# Drop schema, recreate, and migrate
make db-reset

# Seed with demo data
make db-seed

# Drop + migrate + seed in one step
make db-fresh

Graceful degradation

Sagewai continues to function when optional services are absent:

Missing serviceFallbackLimitation
MilvusIn-memory vectorsData lost on restart — development only
NebulaGraphIn-memory graphData lost on restart — development only
RedisDirect database queriesSlower response times, no caching
LocalStackLocal filesystemNo S3-compatible archival
Observability stackNo dashboardsAgents still run; no metrics or tracing

Minimum viable deployment: PostgreSQL only.

make infra-core    # starts PostgreSQL + Redis (~200 MB)
make db-upgrade    # apply migrations
make dev-native APP=admin  # start admin backend