team and repo. Every stack should use at least AWS provider v6. Without a hierarchy mechanism, you duplicate these declarations in every stack’s ubx.iac file — and when the backend bucket name changes, you update it in every file. ubx.root.iac solves this: place it at the repository root and ubx automatically discovers it when validating or applying any child project in the directory tree below it. Backend config, provider version constraints, and shared tags cascade down to every child stack. Children inherit everything from root and can override any attribute locally — root wins only on attributes the child doesn’t declare.
What you’ll learn
- How
ubx.root.iacprovides shared config inherited by all child stacks - The merge rules: child wins on overlap, root fills in what child doesn’t declare
- How
ubx validate --allvalidates the entire hierarchy at once
Why this matters
Code hierarchy is the difference between a platform with consistent defaults and a platform where every team independently decides their backend bucket name.
ubx.root.iac is a single source of truth for org-wide infrastructure conventions — backend, provider versions, mandatory tags — that every stack inherits automatically.The source code
How it works
ubx walks up from the child directory to find ubx.root.iac
When you run
ubx validate from services/api/, ubx walks up the directory tree looking for ubx.root.iac. It finds it two levels up at the repository root. The root discovery happens before compilation — the root config is merged into the child’s compile context.Root and child configs are merged
The merger applies root config as defaults. Child config overrides root on any attribute that appears in both. Tags are deep-merged:
team = "platform" from root plus any child-declared tags coexist. Provider version constraints: child wins if it declares the same provider; root fills in providers the child doesn’t declare.ubx validate --all discovers and validates all children
From the repository root,
ubx validate --all scans for all directories containing a ubx.iac file, applies the root config to each, and validates them all. 2 passed · 0 failed means every child stack in the hierarchy is valid. This is the CI command for a monorepo.Merge rules
| Config type | Merge behaviour |
|---|---|
tags {} | Deep merge — child tags and root tags coexist; child wins on overlapping keys |
provider version | Child wins if same provider is declared in both; root fills in providers child doesn’t declare |
backend | Child’s backend block takes precedence; root backend is ignored if child declares one |
runtime | Child’s ubx.iac runtime wins; root can’t override child runtime |
Common mistakes
Run it
What you learned
ubx.root.iac at the repo root provides shared config inherited by all child stacks below itChild config wins on overlap; root fills in attributes the child doesn’t declare
ubx validate --all from the root validates every child stack in the hierarchy at onceNext steps
Multi-runtime compilation
Compile the same .iac source to TypeScript, Python, or Go
ubx block reference
Full ubx block syntax and all configuration options
Full runnable example: github.com/ubiquex/ubx-examples/41-code-hierarchy-root-and-children

