Cross-Service References
References let a service read another service’s or addon’s values without copy-pasting credentials. They keep each value in one place; consumers pick up changes on their next deploy.
Syntax
${{<name>.<KEY>}}<name>— the target service or addon name (the one shown in the dashboard and used inlizard add -n).<KEY>— a key the target exposes. An addon exposes its connection values. A service exposes its project and service variables and secrets, plus itsLIZARD_*andPORTvalues. It does not expose theDATABASE_URLorREDIS_URLthat Lizard injects from addons; reference the addon for those.
Use them anywhere a value is accepted — most commonly in a secret:
lizard secrets set DATABASE_URL='${{postgres.DATABASE_URL}}' --service apiHow they resolve
- References resolve at deploy time against the values the target exposes.
- References you set in a secret (
lizard secrets setor the dashboard) match the target’s current name. Renaming the target breaks them; update every${{oldname.KEY}}after a rename. References seeded withlizard add -vfollow the target through a rename. - A reference to a missing target or key resolves to an empty string — it does not fail the deploy. The build log prints a warning for each empty reference with the reason.
- Only circular references throw an error.
After wiring a reference, check the build log for empty ones:
lizard logs --build --service api
If a reference isn’t showing up the way you expect, see Troubleshooting → a secret or reference isn’t showing up.
Common patterns
Wire an addon to several services — bind on each consumer; use the private URL inside the project:
lizard secrets set REDIS_URL='${{redis.REDIS_PRIVATE_URL}}' --service api
lizard secrets set REDIS_URL='${{redis.REDIS_PRIVATE_URL}}' --service workerReference another service’s value — e.g. share a computed URL or token. LIZARD_PUBLIC_DOMAIN is a bare hostname and exists once the service has a domain; LIZARD_PRIVATE_DOMAIN (<name>.lizard.internal) reaches the service inside the project:
lizard secrets set UPSTREAM_URL='https://${{api.LIZARD_PUBLIC_DOMAIN}}' --service web
lizard secrets set INTERNAL_API='http://${{api.LIZARD_PRIVATE_DOMAIN}}:8080' --service webReference a second addon of the same type — use its generated name:
lizard secrets set CACHE_URL='${{redis-winter-otter.REDIS_URL}}' --service apiWhy not just use --global?
Putting a shared value in project (--global) scope exposes it to every service, including ones that don’t need it. A reference keeps the value in one place and binds it only where you set it. Note that each service already gets one DATABASE_URL and one REDIS_URL from the project’s Postgres and Redis addons, at the lowest precedence; with several addons of one type, which one is not defined. A reference overrides them. See Secret scoping.
See also
- Variables & Secrets — scopes and precedence.
lizard secrets— the full command reference.
Updated