VariablesCross-Service References

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 in lizard 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 api

How 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 worker

Reference 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 web

Reference a second addon of the same type — use its generated name:

lizard secrets set CACHE_URL='${{redis-winter-otter.REDIS_URL}}' --service api

Why 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

Updated