FEATURES
πΌ Compose: Multi-Workload Deployments
Deploy entire application stacks with a single command using dependency-ordered orchestration.
π Table of Contents¶
- What is aether-compose.yaml?
- Compose Spec Format
- Dependency Resolution
- Commands
- Examples
- Dry-Run Mode
- Policy Gate Integration
- REST API
- Cross-References
π What is aether-compose.yaml?¶
An aether-compose.yaml file groups multiple workloads into a single deployment unit. Instead of deploying each service individually, you declare them all in one file with:
- Dependency ordering -- workloads start in the correct sequence
- Runtime overrides -- pin specific workloads to specific runtimes
- Environment injection -- pass per-workload env vars at deploy time
- Validation -- catch circular dependencies and missing references before anything runs
The default file name is aether-compose.yaml, but you can pass any path to the compose subcommands.
π Compose Spec Format¶
Full Schema¶
version: "1"
workloads:
<workload-name>:
spec: <path-to-workload-yaml>
runtime: <optional-runtime-override>
depends_on:
- <other-workload-name>
env:
KEY: value
Field Reference¶
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
version |
string | Yes | -- | Schema version. Currently "1". |
workloads |
map | Yes | -- | Named workload entries (keys are logical names). |
workloads.<name>.spec |
path | Yes | -- | Path to the workload YAML spec file (relative to compose file). |
workloads.<name>.runtime |
string | No | auto | Runtime override: container, kube, kubevirt, metal. When omitted, the decision engine selects automatically. |
workloads.<name>.depends_on |
list | No | [] |
Names of workloads that must be started before this one. |
workloads.<name>.env |
map | No | {} |
Extra environment variables injected at deploy time. |
Runtime Override Values¶
| Value | Runtime | Icon |
|---|---|---|
container / podman |
Podman | π³ |
kube / kubernetes / k8s |
Kubernetes | βΈοΈ |
kubevirt / vm |
KubeVirt | π₯οΈ |
Minimal Example¶
version: "1"
workloads:
web:
spec: ./web.yaml
Full-Featured Example¶
version: "1"
workloads:
database:
spec: ./db.yaml
runtime: container
env:
POSTGRES_DB: mydb
POSTGRES_USER: admin
api:
spec: ./api.yaml
runtime: kube
depends_on:
- database
env:
LOG_LEVEL: debug
web:
spec: ./web.yaml
depends_on:
- api
π Dependency Resolution¶
aether uses Kahn's algorithm (topological sort) to determine the correct startup order.
Algorithm Steps¶
- Build an in-degree map for all workloads (count of incoming dependencies)
- Seed a queue with zero-dependency workloads (sorted alphabetically for determinism)
- Process each node: add to result, decrement dependents' in-degrees
- If a dependent's in-degree reaches zero, enqueue it (also sorted for determinism)
- If the result is shorter than the workload count, a cycle exists
Resolution Rules¶
| Rule | Behavior |
|---|---|
| No dependencies | Start first (alphabetical tiebreaker among peers) |
| Linear chain | Strict sequential order |
| Diamond pattern | Shared dependency starts first, dependents follow when ready |
| Circular reference | Error: "circular dependency detected in compose workloads" |
| Missing reference | Error: "workload 'X' depends on 'Y' which is not defined" |
Example: Diamond Dependency¶
database (0 deps) βββΊ api (depends on database)
ββββΊ worker (depends on database)
β β
ββββΊ web (depends on api, worker)
Resolved order: database β api β worker β web
Example: Linear Chain¶
database β api β web
Resolved order: database β api β web
β‘ Commands¶
compose validate¶
Validate a compose file for structural correctness without deploying anything.
aether compose validate # default: aether-compose.yaml
aether compose validate ./my-stack.yaml # explicit path
Checks performed:
| Check | Error on failure |
|---|---|
| YAML syntax | "failed to parse compose file" |
depends_on references |
"workload 'X' depends on 'Y' which is not defined" |
| Circular dependencies | "circular dependency detected in compose workloads" |
Output includes: - Workload count - Computed deploy order (topological) - Any validation errors
compose up¶
Deploy all workloads from a compose file in dependency order.
aether compose up # default file
aether compose up ./production-stack.yaml # explicit path
aether compose up --runtime kube # override runtime for all
aether compose up --dry-run # preview without executing
| Flag | Short | Description |
|---|---|---|
--runtime |
-r |
Override runtime for all workloads (ignores per-workload runtime fields) |
--dry-run |
-- | Show the deployment plan without executing |
compose down¶
Stop all workloads defined in a compose file in reverse dependency order (dependents stop first).
aether compose down # default file
aether compose down ./production-stack.yaml # explicit path
π¦ Examples¶
3-Tier Application (db β api β web)¶
Directory layout:
my-app/
βββ aether-compose.yaml
βββ db.yaml
βββ api.yaml
βββ web.yaml
aether-compose.yaml:
version: "1"
workloads:
database:
spec: ./db.yaml
runtime: container
env:
POSTGRES_DB: myapp
POSTGRES_USER: admin
POSTGRES_PASSWORD: "${DB_PASSWORD}"
api:
spec: ./api.yaml
runtime: kube
depends_on:
- database
env:
DATABASE_URL: "postgres://admin:${DB_PASSWORD}@database:5432/myapp"
LOG_LEVEL: info
JWT_SECRET: "${JWT_SECRET}"
web:
spec: ./web.yaml
depends_on:
- api
env:
API_BASE_URL: "http://api:8080"
NODE_ENV: production
Deployment workflow:
# 1. Validate first
aether compose validate
# β
Valid compose file with 3 workloads
# Deploy order: database β api β web
# 2. Preview the plan
aether compose up --dry-run
# 3. Deploy the stack
aether compose up
# 4. Tear down (web stops first, then api, then database)
aether compose down
Microservices with Shared Dependencies¶
version: "1"
workloads:
redis:
spec: ./infra/redis.yaml
runtime: container
postgres:
spec: ./infra/postgres.yaml
runtime: container
env:
POSTGRES_DB: services
auth-service:
spec: ./services/auth.yaml
runtime: kube
depends_on:
- redis
- postgres
user-service:
spec: ./services/users.yaml
runtime: kube
depends_on:
- postgres
gateway:
spec: ./services/gateway.yaml
depends_on:
- auth-service
- user-service
env:
RATE_LIMIT: "1000"
Resolved deploy order: postgres β redis β auth-service β user-service β gateway
Mixed Runtimes with Environment Injection¶
version: "1"
workloads:
ml-model:
spec: ./ml/model-server.yaml
runtime: metal
env:
MODEL_PATH: /models/v3
GPU_MEMORY: "16Gi"
api-gateway:
spec: ./gateway.yaml
runtime: kube
depends_on:
- ml-model
env:
ML_ENDPOINT: "http://ml-model:9090/predict"
CACHE_TTL: "300"
π Dry-Run Mode¶
Preview the deployment plan without executing anything:
aether compose up --dry-run
Dry-run output shows:
- β The resolved deploy order
- β Runtime selection for each workload (auto-decided or overridden)
- β Environment variables that will be injected
- β Any policy violations (see below)
Combine with the global --dry-run flag for consistent behavior:
aether --dry-run compose up
π‘οΈ Policy Gate Integration¶
When the policy gate is enabled, each workload in the compose file is evaluated against your active policy set before deployment begins. If any workload fails a policy check, the entire compose up is aborted.
# Deploy with policy enforcement (default behavior)
aether compose up
# Skip policy checks (use with caution)
aether --skip-policy compose up
Policy checks evaluate each workload's spec individually against the configured rule set. See the Security Guide for the full list of 10 policy rule types.
π REST API¶
POST /api/compose/validate¶
Validate a compose spec via the REST API.
Request: Raw YAML body (Content-Type: text/plain or application/x-yaml)
curl -X POST http://localhost:5090/api/compose/validate \
-H "Content-Type: text/plain" \
-d @aether-compose.yaml
Response (valid):
{
"success": true,
"data": {
"valid": true,
"workload_count": 3,
"deploy_order": ["database", "api", "web"]
},
"error": null
}
Response (invalid -- missing dependency):
{
"success": false,
"data": null,
"error": "workload 'api' depends on 'database' which is not defined in the compose file"
}
Response (invalid -- circular dependency):
{
"success": false,
"data": null,
"error": "circular dependency detected in compose workloads"
}
Response (invalid YAML):
{
"success": false,
"data": null,
"error": "Invalid YAML: ..."
}
π Cross-References¶
| Document | Relevance |
|---|---|
| Security & Policy Guide | Policy gate rules and --skip-policy |
| Plugin System | Custom runtimes available as compose targets |
| Health Monitoring | Health tracking for deployed workloads |
| API Reference | Full REST API documentation |
| Quick Reference | Command cheat sheet |