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 in the target’s merged environment.
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 target’s merged environment.
- They match the target’s current name. Renaming the target breaks them; update every
${{oldname.KEY}}after 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 every running Postgres and Redis addon’s DATABASE_URL and REDIS_URL reach every service anyway, at the lowest precedence; a reference overrides them. See Secret scoping.
See also
- Variables & Secrets — scopes and precedence.
lizard secrets— the full command reference.
Updated