Local Stack
The Docker Compose configuration in the repository root starts all Causet services and their infrastructure dependencies. Use this for local development and integration testing.
Start the stack
docker compose up -dThis pulls and starts all containers in detached mode. First run takes longer because images are pulled.
What starts
| Container | Port | Purpose |
|---|---|---|
causet-runtime-service | 8080, 9090 | Intent processing, rule evaluation, ledger writes |
causet-query-service | 8082 | Named query execution |
causet-projection-worker | — | Kafka consumer, projection UPSERT |
causet-saas-cloud | 8085 | Control plane API |
causet-cloud-control-plane | 3000 | Web UI |
ws-gateway-go | 8081 | WebSocket gateway |
postgres | 5432 | PostgreSQL (causet + projections databases) |
redpanda | 9092, 9644 | Kafka-compatible broker |
redis | 6379 | IR artifact cache |
minio | 9000, 9001 | S3-compatible object store |
Startup order
Services wait for their dependencies to become healthy before starting. The order is:
postgres → redpanda → redis → minio
→ causet-saas-cloud
→ causet-runtime-service
→ causet-projection-worker
→ causet-query-service
→ causet-cloud-control-plane
→ ws-gateway-goOn first start, you also need to initialize infrastructure before the application services will work correctly:
# Create Kafka topics
./infra/redpanda/create-topics.sh
# Create MinIO bucket
./infra/minio/create-buckets.sh
# Initialize PostgreSQL schemas
psql $DATABASE_URL -f infra/postgres/init.sql
psql $DATABASE_URL -f infra/postgres/02-projections-schema.sqlNote: These scripts are idempotent. Running them more than once is safe.
MinIO (local S3)
MinIO runs on port 9000 (API) and 9001 (console). IR artifacts are stored in the causet-artifacts bucket.
Access the MinIO console at http://localhost:9001. Default credentials are in docker-compose.yml (typically minioadmin / minioadmin).
# Verify the bucket exists
mc alias set local http://localhost:9000 minioadmin minioadmin
mc ls local/causet-artifactsRedpanda (local Kafka)
Redpanda runs on port 9092 (Kafka protocol) and 9644 (admin API). Topics are created by ./infra/redpanda/create-topics.sh.
Required topics:
| Topic | Purpose |
|---|---|
causet.intents.v1 | Inbound intents (optional, can use HTTP directly) |
causet.ledger-events.v1 | Committed ledger events |
causet.projection-events.v1 | Projection events consumed by projection worker |
causet.projection-dlq.v1 | Dead-letter queue for failed projection handlers |
causet.patches.v1 | State patch events |
# List topics
rpk topic list --brokers localhost:9092
# Consume from a topic
rpk topic consume causet.ledger-events.v1 --brokers localhost:9092PostgreSQL
Postgres runs on port 5432. Two databases are used:
causet— event store (ledger_events, intent log, entity state)projections— projection tables per tenant
# Connect to causet database
psql postgresql://localhost:5432/causet
# Connect to projections database
psql postgresql://localhost:5432/projections
# Check that ledger_events table exists
psql postgresql://localhost:5432/causet -c "\dt"Tenant schemas are created when you deploy a release to a fork. The schema name follows the pattern {platformId}_{applicationId}_{forkId}.
Health checks
Verify each service is healthy:
# Runtime service
curl -s http://localhost:8080/actuator/health | jq .
# Query service
curl -s http://localhost:8082/actuator/health | jq .
# SaaS / control plane API
curl -s http://localhost:8085/actuator/health | jq .
# Projection worker (internal port, check via docker)
docker exec causet-projection-worker curl -s http://localhost:8083/actuator/healthExpected response for a healthy service:
{
"status": "UP",
"components": {
"db": { "status": "UP" },
"kafka": { "status": "UP" },
"s3": { "status": "UP" }
}
}Tail logs
# All services
docker compose logs -f
# Specific service
docker compose logs -f causet-runtime-service
docker compose logs -f causet-projection-worker
# Follow projection worker DLQ errors
docker compose logs -f causet-projection-worker | grep -i "dlq\|error\|failed"Stop the stack
# Stop containers, preserve volumes
docker compose down
# Stop and remove all volumes (destroys all data)
docker compose down -vCommon startup issues
Port conflicts
If a port is already in use, Docker Compose will fail to start the conflicting container. Check what’s using the port:
lsof -i :8080
lsof -i :5432Either stop the conflicting process or edit docker-compose.yml to use a different host port.
Postgres not ready
Services start before Postgres has finished initializing. The compose file uses health checks to gate startup, but if you see connection refused errors in the first 30 seconds, wait and retry.
# Check postgres health
docker inspect postgres --format '{{.State.Health.Status}}'If Postgres stays unhealthy, check its logs:
docker compose logs postgresRedpanda topic creation fails
If create-topics.sh returns errors, Redpanda may not be ready yet. Wait 10–15 seconds and retry:
docker compose logs redpanda
./infra/redpanda/create-topics.shMinIO bucket missing
If you see S3 errors in service logs, the bucket may not exist. Run:
./infra/minio/create-buckets.shServices restart-looping
If a service exits and Docker restarts it repeatedly, check its logs for the error before it exits:
docker compose logs --tail=50 causet-runtime-serviceMost common causes: missing environment variable, database unreachable, IR artifact not found on S3.
Reset everything
To start completely fresh:
docker compose down -v
docker compose up -d
./infra/redpanda/create-topics.sh
./infra/minio/create-buckets.sh
psql postgresql://localhost:5432/causet -f infra/postgres/init.sql
psql postgresql://localhost:5432/projections -f infra/postgres/02-projections-schema.sql