Full dependency graph
This example looks more like an application: setup fans out to two APIs, both fan in to a gateway, and a worker waits for the gateway.
The graph
Every component is still safe and local. The APIs are tiny Python servers and the migration script only prints progress.
Run it
cd examples/full-stack
kranz -f kranz.yamlExplicit -f avoids the adjacent process-compose.yaml, which is included for format comparison.
Guided scenario
- Focus
orders-workerand presss. - Kranz expands the dependency closure before starting anything, so queued intent is visible across the graph.
migratecompletes once.catalog-apiandbilling-apistart in parallel.gatewaywaits for both readiness probes.orders-workerstarts after gateway readiness and begins polling it.
Pin gateway logs with Shift+3, then focus the worker. You can now compare the upstream request log and worker output at the same time.
Important configuration patterns
The gateway has two health-gated dependencies:
gateway:
depends_on: [catalog-api, billing-api]
dependency_conditions:
catalog-api: {condition: process_healthy}
billing-api: {condition: process_healthy}The worker has an explicit failure policy:
availability:
restart: on_failure
backoff: 2s
max_restarts: 3Recovery applies to process exits. It does not automatically restart detached external resources whose status changes outside Kranz.
Experiments
- Stop one API and observe reverse dependency shutdown.
- Start only
gateway; the two APIs and setup are included, but the worker is not because it is a dependent, not a dependency. - Compare
kranz.yamlwithprocess-compose.yamlin the same directory. - Filter logs with
/, then usenandNto move between matches.
Ports and cleanup
| Service | Port |
|---|---|
| catalog-api | 18881 |
| billing-api | 18882 |
| gateway | 18883 |
Press a, then s, and confirm. All three listeners and the worker process are owned and released by Kranz.