Variables & Outputs
How configuration and cross-component data flow into a deployment
The data layer answers two questions: how do you configure a component differently per environment, and how does one component hand data to another? Variables and Outputs cover those two cases.
Two kinds of values
- Variables are configuration you set. They are referenced in templates as
.var. - Outputs are values captured from a component after it deploys. They are referenced as
.component.NAME.OUTPUTand are how data flows downstream.
Both feed the same rendering step, but they come from opposite ends: variables are inputs you provide, outputs are facts a deployment produces.
Variables: per-environment configuration
A variable is config scoped to an environment. The same component deployed to dev and prod renders against each environment's own variables, so one definition produces environment-appropriate results.
.var.region → "us-east-1" (prod) / "us-west-2" (dev)
.var.instance_size → "large" (prod) / "small" (dev)Variable overrides can also ride inside a changeset, so a value change is staged and reviewed alongside the component changes it affects.
Outputs: cross-component data flow
When a component applies, it can emit outputs - a database endpoint, a VPC ID, a generated secret reference. Those outputs are captured into the environment's value store and become available to other components as .component.NAME.OUTPUT.
This is what makes the dependency graph more than ordering. A downstream component does not just wait for its upstream; it reads the upstream's outputs:
database component ──applies──▶ output: connection_string
│
▼
api component values: DATABASE_URL = .component.database.connection_stringBecause outputs only exist after the upstream applies, a run defers any component that references an upstream output until that upstream has actually deployed. Then it renders the downstream against the concrete value and applies it. (See the wavefront.)
The render namespaces
At apply, each component's values template renders against four namespaces:
| Namespace | Holds |
|---|---|
.var | environment variables you set |
.component | outputs captured from other components |
.self | the component's own identity and metadata |
.app | application-level context |
The result is the fully resolved set of values, which is frozen onto the component's Revision. That snapshot - not the live template - is exactly what deployed, and exactly what a rollback replays.
Rendering happens at apply, against the values that exist at that moment. This is why output-dependent components must wait: rendering them earlier would template against data that does not exist yet.
Putting it together
You set ─▶ .var ┐
├─▶ render at apply ─▶ Revision (frozen values)
Upstream ─▶ .component ┘
emits outputsVariables let one definition serve many environments. Outputs let many components compose into one system. Together they are why an environment can be described once and deployed correctly everywhere.