resource.res.property, and formae fills in the real value at apply time, once the resource that produces it has actually been created.
Resolvables exist for two things:
- Referencing properties of other resources (a subnet needs a VPC ID, a database needs subnet IDs).
- Referencing secrets without ever exposing their value.
The examples below use
local to bind a resource to a variable so it can be referenced later via .res. A local still has to be mentioned inside the forma block to actually be created. See Write your first forma for the full pattern.Why resolvables exist
Infrastructure resources depend on each other, and the values they depend on often don’t exist until the dependency is created (an AWS-generated ID, an ARN, a randomly generated password). Resolvables let you write that dependency declaratively, without manually ordering resources or copying values by hand. formae:- Detects when a referenced property is available.
- Waits for it if the resource that produces it is still being created.
- Injects the resolved value at the right point in the apply.
vpc.res.vpcId in a subnet’s definition even though the VPC doesn’t exist yet: formae works out that the subnet depends on the VPC, creates the VPC first, and substitutes the real ID.
Referencing resource properties
Referencing secrets
A secret is created like any other resource, then referenced through.res the same way. Wrapping the value with formae.value(...).opaque keeps it out of logs, output, and CLI results while still letting other resources consume it.
formae.value()wraps the password..opaquemarks it as a secret that is never displayed..setOncegenerates it once and reuses that value on every subsequent apply.dbSecret.res.secretStringreferences the secret’s value in the database configuration.
.opaque and .setOnce.
Embedding resolvables in strings
.res gives you a resolvable as a field’s entire value. Sometimes you need to splice a resolved value into the middle of a larger string, for example, a value that only exists after another resource is created, but has to appear inside a code block or config template.
formae.embed(...) does this: write the surrounding text as a string and interpolate any resolvable with \(...). formae resolves each reference at apply time and substitutes the real value into the text. Both resources still apply in a single pass, the referenced resource is ordered first automatically.
A CloudFront Function whose JavaScript needs the generated ID of a Key Value Store is the canonical case. Without embedding you would apply the store, copy its ID by hand, and re-apply the function. With it, one apply does both:
\(store.res.id) becomes the real Key Value Store ID (for example a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d), and the function is created with that value already in its source.
A few things to know:
- A field has to opt in to accept embeds. The plugin’s schema decides whether a field can be embedded. If a field rejects
formae.embed(...), reference the whole value with.resinstead. formae extractround-trips embeds. Extracting a managed resource regenerates theformae.embed("…\(…)…")call rather than the resolved value, so re-applying is a no-op and the reference is never flattened to a literal.- You can embed more than one reference in the same string, and mix them with
formae.value(...)secrets exactly as in any other field.
Resolvables in targets
Resolvables aren’t limited to resource properties, they can also appear in target configurations. This enables cross-plugin patterns where one plugin provides infrastructure and another plugin’s target resolves its connection details from it:at() method indexes into the endpoints Mapping by key: formae resolves it to the actual URL (for example http://localhost:3000) at apply time. See Target resolvables for the full pattern.
Collection resolvables
When a resource property resolves to a collection (Mapping or Listing), useat() to reference individual items:
See also
- Values: the
.opaqueand.setOncemodifiers used with secrets. - Target: target resolvables and cross-plugin connection resolution.
- Properties: the CLI-facing counterpart to resolvables.

