# Variable references

> Connect services with ${{ service.KEY }} references in Falak — syntax, name matching, variables databases expose, resolution at deploy time and errors.

Source: https://falak.sh/docs/guides/variable-references/

A **variable reference** lets one service use another service's variable without copying secrets around. Write `${{ <service>. }}` in a site variable; Falak replaces it with the current value when it deploys.

```dotenv title="Site variables of 'web'"
DATABASE_URL=${{ shop-db.DATABASE_URL }}
API_BASE_URL=https://${{ api.APP_DOMAIN }}/v1
MAIL_FROM=${{ shared-config.MAIL_FROM }}
```

## Syntax

- `${{ service.KEY }}` — whitespace inside the braces is allowed.
- `service` is the **service name** on the canvas. It matches case-insensitively, and spaces, dots and underscores count as dashes: a service named `Shop DB` or `shop_db` is `shop-db`.
- `KEY` is a variable of that service.
- References can be embedded in longer values, as `API_BASE_URL` shows.

## What a service exposes

| Service kind | Keys |
|---|---|
| **Site** | All of its own variables (resolved themselves) |
| **Database** (PostgreSQL, MySQL, MariaDB) | `DATABASE_URL`, `DB_CONNECTION`, `DB_HOST`, `DB_PORT`, `DB_DATABASE`, `DB_USERNAME`, `DB_PASSWORD` |
| **Database** (Redis, Valkey) | `REDIS_URL`, `REDIS_HOST`, `REDIS_PORT`, `REDIS_PASSWORD`, `REDIS_CLIENT` |

For databases:

| Key | Value |
|---|---|
| `DB_CONNECTION` | `pgsql`, `mysql` or `mariadb` (Laravel driver names) |
| `DB_HOST` | A dedicated database server's most private address: WireGuard private network address → provider private IPv4 → public IPv4 → IPv6. For an engine on an app or worker server: `127.0.0.1` for a native site, the server's own address for a container (see below) |
| `DB_PORT` | The engine's port on that server |
| `DB_DATABASE` | The database name |
| `DB_USERNAME`, `DB_PASSWORD` | The oldest user granted access to the database (users with all privileges first) |
| `DATABASE_URL` | `postgresql://user:pass@host:port/db` or `mysql://user:pass@host:port/db` (URL-encoded) |

Only **database servers** (type `db`) make the engine listen on the network. An engine on an **app** or **worker** server serves that server only, so `DB_HOST` / `DATABASE_URL` resolve only for a consumer running on that server alone:

- a **native** site gets `127.0.0.1`;
- a **container** on it (Docker site, Compose stack, function) gets the server's own address (private network → provider private IP → public IP), which it reaches through the Docker bridge. This needs agent 0.4.5 or newer; see [Containers and databases on the same server](/docs/databases/create-databases/#containers-and-databases-on-the-same-server).

A site on other servers gets a deploy error naming the reason instead of a host it cannot reach. Use a dedicated database server for those, and [open its firewall](/docs/databases/remote-access/) to them.

For Redis and Valkey instances:

| Key | Value |
|---|---|
| `REDIS_URL` | `redis://default:<password>@host:port` |
| `REDIS_HOST`, `REDIS_PORT` | The instance's host for this site (below) and its own port (6380–6479) |
| `REDIS_PASSWORD` | The `default` user's password |
| `REDIS_CLIENT` | `phpredis` |

Unlike SQL engines on app servers, a Redis or Valkey instance can serve the whole environment (since v0.7.1, agents with `db.redis.network`). `REDIS_HOST` / `REDIS_URL` depend on where the site runs:

- a **native** site on the instance's server gets `127.0.0.1`;
- a **container** on it (Docker site, Compose stack, function) gets the Docker bridge's address (`docker0`, `172.17.0.1` out of the box);
- a site on **another server** of the environment (native, containers, or both) gets the instance server's address on a private network both servers share: a Falak WireGuard private network first, else the provider's private network — only for DigitalOcean or Lightsail servers created with the same provider credential in the same region.

A Redis or Valkey reference never resolves to a public address. Servers that share no private network get a deploy error asking you to add both servers to a private network (**Network → Private networks**). An instance on a server whose agent predates v0.7.1 listens on `127.0.0.1` only, so everyone but native sites on that server gets an error asking you to update the agent. See [Network access](/docs/databases/redis-and-valkey/#network-access).

## Scope

References resolve against services in the **same environment** of the same project. After you duplicate `production` into `staging`, the same `${{ shop-db.DATABASE_URL }}` points at staging's `shop-db`.

## When references resolve

At deploy time, in three places:

1. the release's `.env` and the processes' environment;
2. the deploy script's environment;
3. public build variables (those the build can see).

The resolved values are stored with the release, so a rollback uses the values that release was deployed with.

## Errors

A reference to an unknown service or key, or a cycle (`a` references `b` which references `a`), fails the deployment before anything changes on your servers:

```text title="Example deployment errors"
Unresolved variable references: DATABASE_URL: unknown service "shopdb" in ${{ shopdb.DATABASE_URL }}.
Unresolved variable references: DB_PASS: service "shop-db" has no variable PASSWORD (it exposes DB_CONNECTION, DB_HOST, …).
Unresolved variable references: A: reference cycle … .
Unresolved variable references: DB_HOST: shop-db.DB_HOST cannot be used here: api runs on app-2, but the database runs on app-1, which accepts connections from that server only (move it to a dedicated database server to reach it from elsewhere).
Unresolved variable references: DB_HOST: shop-db.DB_HOST cannot be used here: api runs in a container, but containers on app-1 can't reach its databases yet: update the server's agent (container access needs agent 0.4.5 or newer).
Unresolved variable references: REDIS_URL: … shares no private network with <server>, and the Redis instance … is never exposed on a public address. Add both servers to a private network (Network → Private networks).
```

Fix the variable and deploy again.

## On the canvas

Every reference draws a dashed arrow from the site to the referenced service. In the Variables tab, a reference links to its service; clicking it opens that service's panel on top.

## Templates and Compose

Template inputs can default to references, for example `${{ postgres.DATABASE_URL }}`, and Compose sites get the resolved values in their project `.env`. See [Custom templates](/docs/templates/custom-templates/).

## Next steps
