Dependencies
Infrastructure

Dependencies

Define startup order, health conditions, and cross-deployment references so your services and deployments start in the right sequence every time.

Dependencies control the startup order of your services and deployments. When one service needs another to be running first, you declare that relationship in your JuhJuh File and JuhJuh handles the rest: health checks, ordering, parallel execution where possible, and validation that no circular chains exist.

Service dependencies

Services declare dependencies in two ways: explicit dependsOn entries and implicit dependencies through links.

Explicit dependencies

Add a dependsOn block to any service that needs another service or resource running first:

yaml services: web: type: web dependsOn: api: condition: service_healthy migrations: condition: service_completed_successfully

Each entry maps a service or resource name to a condition that must be satisfied before the dependent service starts.

Conditions

Condition Behavior
service_started Proceed as soon as the dependency's container begins running
service_healthy Wait for the dependency's health check to pass
service_completed_successfully Wait for the dependency to finish with exit code 0 (useful for one-off jobs like migrations)

service_healthy is the most common choice. Use service_started when you only need the process to be up, and service_completed_successfully for init jobs or migration tasks that must finish before the next service begins.

When you link a service to a resource, JuhJuh creates an automatic dependency with service_healthy condition. You do not need to also add an explicit dependsOn for the same resource.

yaml services: web: type: web links: - postgres - redis

In this example, web automatically waits for both postgres and redis to pass their health checks before starting. The linked resources also inject their connection environment variables into the service.

Template inheritance

If a service extends a template, it inherits the template's dependencies. A service can override inherited dependencies by declaring its own dependsOn block.

```yaml templates: base-app: dependsOn: postgres: condition: service_healthy

services: web: extends: base-app # Inherits postgres dependency from base-app worker: extends: base-app dependsOn: redis: condition: service_healthy # Overrides with its own dependencies ```

Deployment dependencies

Deployments can depend on other deployments. This is how you coordinate multi-VM infrastructure where, for example, a database VM must be healthy before the application VM starts deploying.

```yaml deployments: database: vm: db-server resources: [postgres] expose: - port: 5432 as: postgres

app: vm: app-server services: [web, worker] dependsOn: - deployment: database condition: healthy ```

Deployment conditions

Condition Behavior
started Proceed once the dependency's deployment begins
healthy Wait for the dependency to reach a healthy state (default)
completed Wait for the dependency to finish entirely

If you omit condition, it defaults to healthy.

Parallel execution with levels

JuhJuh groups deployments into levels based on their dependency graph. Deployments at the same level run in parallel. Deployments at level N only start after all level N-1 deployments succeed.

```yaml deployments: postgres-primary: vm: db-1 resources: [postgres]

redis-cache: vm: cache-1 resources: [redis]

api: vm: app-1 services: [web, worker] dependsOn: - deployment: postgres-primary condition: healthy - deployment: redis-cache condition: healthy

frontend: vm: web-1 services: [static-site] dependsOn: - deployment: api condition: healthy ```

graph TB
    subgraph "Level 0 (parallel)"
        pg[postgres-primary]
        redis[redis-cache]
    end
    subgraph "Level 1"
        api[api]
    end
    subgraph "Level 2"
        fe[frontend]
    end
    pg --> api
    redis --> api
    api --> fe

In this setup, postgres-primary and redis-cache deploy in parallel (level 0). Once both are healthy, api starts (level 1). After api succeeds, frontend begins (level 2).

Deployment references

Once a deployment is running, other deployments can reference its runtime values using ${deployment.<name>.<attribute>} syntax. This is how services on one VM discover services on another.

yaml envGroups: app-config: clear: POSTGRES_HOST: "${deployment.database.host}" POSTGRES_PORT: "${deployment.database.port.postgres}" DATABASE_URL: "postgres://user@${deployment.database.endpoint.postgres}/mydb"

Available attributes

Attribute Returns Example value
host Private IP of the deployment's VM 10.0.1.5
port.<alias> Port number for a named exposed service 5432
endpoint.<alias> Combined host:port 10.0.1.5:5432
status Current deployment status HEALTHY
network Network name the deployment belongs to internal

The <alias> in port and endpoint matches the as field from the deployment's expose configuration.

Dependency requirement

Any deployment you reference with ${deployment.<name>.<attribute>} must also appear in your dependsOn list. JuhJuh enforces this during validation. If you reference a deployment without declaring a dependency on it, the config fails validation with an error identifying the missing dependency.

This rule exists because deployment references resolve at deploy time. Without a dependency, the referenced deployment might not exist yet, producing an unresolvable reference.

Validation

JuhJuh validates your dependency graph during both juhjuh validate and juhjuh apply. Three checks run automatically:

1. Target existence

Every deployment referenced in a dependsOn entry must be defined in the same config. Referencing a deployment that does not exist produces an error naming the missing target.

2. Circular dependency detection

JuhJuh uses topological sorting to detect cycles. If deployment A depends on B, B depends on C, and C depends on A, validation fails and reports which deployments form the cycle.

Error: circular dependency detected among deployments: A, B, C

3. Reference validation

Every ${deployment.<name>.<attribute>} reference is traced back to the deployment's dependsOn list. If the referenced deployment is not listed as a dependency, validation fails. This check traverses through services, templates, and environment groups to find all references.

Environment overrides

Environments can modify dependencies for specific contexts. A staging environment might remove a dependency that only applies in production, or add a test database dependency that does not exist in the production config.

yaml environments: staging: services: web: dependsOn: staging-db: condition: service_healthy

When an environment overrides a service's dependsOn, the override replaces the base dependencies entirely for that service in that environment.

Best practices

Prefer healthy over started. The started condition only confirms a container is running, not that the service inside it is ready to accept connections. Unless you have a specific reason to use started, default to healthy.

Keep dependency chains short. Deep chains (A depends on B depends on C depends on D depends on E) serialize your deployment and slow down the overall process. Where possible, structure your infrastructure so deployments at the same level can run in parallel.

Use exposed ports for cross-deployment communication. When deployment A needs to reach a service in deployment B, expose the port in B's config and reference it with ${deployment.B.port.alias} or ${deployment.B.endpoint.alias}. This keeps connection details dynamic and avoids hardcoded IPs.

Validate before applying. Run juhjuh validate to catch missing targets, circular dependencies, and unresolved references before starting a deploy. Add --strict to treat warnings as errors.

  • Deployments for creating, rolling back, and managing deployment lifecycle
  • JuhJuh File for the full configuration reference including services, resources, and templates
  • VMs for provisioning the compute instances that deployments target
  • Vault for managing secrets injected into deployments at deploy time
  • Infrastructure Overview for the full platform architecture
  • CLI for running validation, apply, and deployment commands