--- title: "Variables & Outputs" canonical: "https://admiral.io/docs/concepts/variables-and-outputs" description: "How configuration and cross-component data flow through a deployment: variables set per-environment config, and outputs captured after apply feed downstream." --- # Variables & Outputs 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 [#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.OUTPUT` and 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 [#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 [#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_string ``` Because 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](https://admiral.io/docs/concepts/changesets-and-runs.md#applying).) ## The render namespaces [#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. > **Note:** 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 [#putting-it-together] ``` You set ─▶ .var ┐ ├─▶ render at apply ─▶ Revision (frozen values) Upstream ─▶ .component ┘ emits outputs ``` Variables 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. ## Where to go next [#where-to-go-next] - [Changesets & Runs](https://admiral.io/docs/concepts/changesets-and-runs.md): How rendering and output capture sequence during a run - [Applications & Components](https://admiral.io/docs/concepts/applications-and-components.md): Where dependencies between components are declared