Skip to content

Global variables

Beta feature

Global variables are currently in beta. The portal labels the feature with a Beta badge in the sidebar; behavior and UI labels may still change before general availability.

Global variables let you define configuration once, at the organization level, and reuse it across many projects and environments. A deployment pulls in a whole set of these variables with a single reference, and you update the value in one place instead of editing every project that uses it.

The problem they solve

Without global variables, configuration that is shared by several projects has to be duplicated into each one. A typical example is a Redis cluster used by five different services:

  • You copy REDIS_HOST, REDIS_PORT, and REDIS_PASSWORD into all five projects, and into each environment (develop, production) of every project.
  • When the password rotates, you edit the value in 5 projects × 2 environments = 10 places. Miss one and that service breaks.
  • Adding a new setting (say REDIS_DB_INDEX) means touching every project again.
  • There is no single source of truth — the values drift apart over time.

Global variables remove the duplication:

  • Define the Redis configuration once as a group, with a value set per environment (DEV, PROD).
  • Each project assigns the group and picks which value set each environment uses.
  • Rotating the password is a single edit that reaches every project and environment that consumes the group.
  • Adding REDIS_DB_INDEX to the group makes it available everywhere — no change to any project's quix.yaml.

With global variables, one group is the single source of truth that every project draws from — so a change is made once, not copied into each project.

How global variables are organized

Global variables is the organization-scoped feature as a whole — not a single value. A value is built from three pieces:

Term What it is
Variable group A named, organization-level container of related variables — for example redis-config. It has an immutable identifier (used in quix.yaml), a display name, and an optional description. It is the unit a project assigns.
Value set A named variant within a group — for example DEV and PROD. Every variable in the group holds one value per value set, so the same group supplies different values in different environments.
Variable A key/value pair inside a group (a row under the group's Variables tab). Its name becomes the environment-variable name injected into the container. It can be marked secret, in which case the value is encrypted at rest and hidden in the UI, the YAML view, and Git.

A project consumes a group through an assignment, and a group can be assigned at two levels that coexist:

  • A project-level assignment picks the value set used by every environment in the project. In the Global variables tab this is the Default column.
  • An environment-level assignment sets the value set for a single environment, overriding the default. Each environment has its own column in that tab.

Where both exist, the environment-level assignment wins; an environment with no assignment of its own falls back to the project-level Default.

One reference injects the whole group

A deployment references a group once in quix.yaml, and Quix injects every variable in the resolved value set as separate environment variables. You never list the individual variables — and adding a variable to the group later reaches every deployment that already references it, with no YAML change. See Pattern 2: bind a whole group.

When to use global variables

Reach for global variables when the same configuration is consumed by more than one project — shared infrastructure, shared third-party credentials, or any set of values you want to rotate in one place instead of copying into every project. See Which kind of variable do you need? for the full decision guide against project variables, environment variables, and Quix variables.

Global variables vs project variables

Both can hold per-environment values and secrets, so the deciding factors are scope and shape:

  • Scope — project variables belong to one project; global variables are organization-wide, shared by every project that assigns the group.
  • Grouping — global variables come bundled in a group of related keys; a project variable is a single value.
  • Injection — one inputType: VariableGroup reference injects every variable in the group at once; a project variable is bound one key at a time (inputType: ProjectVariable + variableKey).

Use project variables for values a single project owns; reach for a global variable group when the same set of values is shared across projects and you want to define, rotate, and inject them together.

How it works end to end

Setting up and consuming global variables is four steps, split between an organization admin and a project developer:

  1. An organization admin creates the group and its value sets.
  2. The admin adds variables and supplies one value per value set.
  3. A project developer assigns the group to a project and selects the value set for each environment.
  4. The developer references either one group member or the whole group from quix.yaml.

The rest of this page walks through each step.

Set up a variable group

(Organization level — Global Variables in the organization sidebar.)

Create the group

  1. In the Quix Cloud portal, open the organization sidebar and select Global Variables.

    The Redis config group in the organization's Global Variables settings

  2. Click New variable group.

  3. Enter an identifier, a display name, and an optional description. The identifier is what you reference in quix.yaml and cannot be changed after creation. It accepts letters, digits, hyphens, and underscores (up to 254 characters) and must start with a letter or digit. Identifiers are compared case-insensitively when checking for duplicates, so redis-config and Redis-Config cannot both exist.
  4. Add one or more value sets, for example DEV and PROD.
  5. Click Save.

Creator override

The user who creates a group can update it, add value sets, and manage its assignments even if their role lacks the general Update permission. The override does not cover deletions: deleting the group still requires the Delete permission, and deleting a value set requires the Update permission. Reading and creating groups also require the standard permissions.

Add variables

  1. Open the group from the Global Variables list.
  2. Add a row to the variables grid.
  3. Enter the variable name. This becomes the environment-variable name in the container, so it must follow OS conventions: no spaces; we recommend [a-zA-Z_][a-zA-Z0-9_]*. The same name applies across every value set.
  4. Enter a value for each value set — for example a development value and a production value.
  5. To protect the value, toggle Secret. Secret values are encrypted at rest and hidden in the UI, the YAML view, and Git.
  6. Save the row.

Editing a value updates every project and environment that resolves against that value set.

Turning a secret back into a plain value

You can clear the Secret toggle to make a variable plain again, but you must enter a new value in the same edit. A demotion with no new value is rejected — the platform never exposes the stored encrypted value as plaintext.

Assign a group to a project

(Project level — Variables in the project sidebar → Global variables tab.)

A project must assign a group before any of its deployments can reference the group's variables.

  1. Open your project, select Variables in the sidebar, and switch to the Global variables tab. (The sibling Project variables tab holds this project's own variables.)

    The Global variables tab in the project's Variables panel, with assigned groups

  2. Click Assign variable group. (If the group does not exist yet, the empty state also offers Create new group, which opens the org-level dialog.)

  3. In the dialog, pick the group, then the default value set for this project. The dialog orders its fields to match where you started: from the project, the project and environment are already filled in; from Global Variables at the org level, you pick the project and environment instead.
  4. Save the assignment.

The project now resolves every variable in the group against the chosen value set.

Who can manage global variables

The groups offered in the assignment dialog are gated by your role's globalVariable permission. Admin and Manager can create, edit, and delete groups and value sets; Editor can view and edit existing ones but cannot create or delete them; Viewer has read-only access; Operator has none. See Roles and permissions. Ask an organization admin if a group you expect is missing.

Override the value set per environment

The Global variables tab lists each assigned group as a row, with a Default column (the project-level assignment) and a column for each environment. The Default value set applies to every environment that doesn't have its own. To make one environment use a different value set:

  1. In the group's row, open the value set dropdown for the environment you want to change (not the Default column).
  2. Pick a different value set — for example PROD.

    Choosing a value set for an environment from the per-environment dropdown

That environment now uses its own value set; the others keep following the Default. Clearing an environment's selection makes it fall back to the Default again.

Pattern 1 — Substitute a group member into a quix.yaml field

To substitute a single non-secret member's value directly into a quix.yaml field, wrap groupId:variableKey in double curly braces. The substitution happens at sync time, the same as a project variable's {{ }} reference — see Variables overview for how the two patterns compare.

Sizing values are a good fit for substitution, because they belong in a quix.yaml field rather than in the container's environment. The example below uses a second organization-level group, release-tiers, which holds a REPLICA_COUNT member in each of its DEV and PROD value sets:

deployments:
  - name: my-service
    resources:
      replicas: {{release-tiers:REPLICA_COUNT}}

Quix resolves release-tiers:REPLICA_COUNT against the value set currently assigned to the environment — the same assignment a group-level reference uses. If develop is assigned the DEV value set and production is assigned PROD, the same quix.yaml line renders replicas: 1 in one environment and replicas: 3 in the other, and re-syncing each environment after the value changes picks it up.

Format and secrets

Use the exact groupId:variableKey form. Spaces around the colon, a missing identifier, or additional colons cause the sync to fail. Spaces just inside the braces, as in {{ redis-config:HOST }}, are allowed.

Secret group members cannot be substituted with {{ }}. Bind the entire group with inputType: VariableGroup instead. See Why secrets are never substituted for the rule and supported alternatives.

See Template reference for the complete syntax rules and Template resolution and failure modes for exact sync diagnostics.

{{ groupId:variableKey }} works in quix.yaml only

An application defines a group in app.yaml; it cannot substitute a member's value into an app.yaml field, and neither can a code sample's library.json. Keep member substitutions in quix.yaml — see Where references work.

Pattern 2 — Bind a whole group to container environment variables

To pass a global-variable group to your application as environment variables, add one entry under variables with inputType: VariableGroup and the group's identifier in variableGroupId:

deployments:
  - name: Order processor
    application: order-processor
    deploymentType: Service
    variables:
      - name: redis                 # label only — not injected
        inputType: VariableGroup
        variableGroupId: redis-config
        required: true

At deploy time, Quix resolves the group against the value set currently assigned to the environment and injects every variable in that value set as a separate environment variable. If redis-config contains REDIS_HOST, REDIS_PORT, and REDIS_PASSWORD, all three appear in the container. This is different from Pattern 1: it does not substitute a descriptor field, and it cannot select one member.

  • One reference, many env vars. You do not list the individual variables. Adding a variable to the group later reaches this deployment when it is redeployed.
  • The name field is a label. It identifies the reference in the UI and in error messages but is not injected. The injected names come from the variables defined inside the group.
  • The binding is additive. It can sit alongside {{ groupId:variableKey }} references; adding it does not replace or alter those separate substitutions.

To pull in more than one group, add one entry per group. Do not let groups have overlapping member keys; their iteration order is not a public contract.

Required references

Set required: true to make the deployment fail fast at deploy time when the group cannot be resolved. A non-required reference that cannot be resolved is logged and skipped, and the container starts without those variables.

Define a group in app.yaml

The examples above put the reference in quix.yaml. You can also declare it on the application in its app.yaml — then it travels with the app, and every deployment of that app inherits the reference.

app.yaml can go further and carry the group's full definition: its variableGroupId, variableGroupName, variableGroupDescription, and the nested variables: that make up the group. Each nested variable has a key, description, defaultValue, secret, and required.

# app.yaml — the application declares the group and its variables
variables:
  - name: redis
    inputType: VariableGroup
    variableGroupId: redis-config
    variableGroupName: Redis config
    variableGroupDescription: Shared Redis connection
    required: true
    variables:                          # the group's variables
      - key: REDIS_HOST
        description: Redis server hostname
        defaultValue: localhost
        secret: false
        required: true
      - key: REDIS_PASSWORD
        description: Redis auth password
        secret: true
        required: true
      - key: REDIS_PORT
        description: Redis server port
        defaultValue: "6379"
        secret: false
        required: false

Nested variables live in app.yaml only

The nested variables: list belongs to the application definition. A deployment in quix.yaml only ever references the group by variableGroupId — it never lists the group's nested variables. At deploy time the actual values come from the value set assigned to the environment, not from this schema.

See YAML 1.0 and 2.0 for how a deployment inherits these declarations from app.yaml.

Access the values from your code

Each variable in the resolved value set arrives as a standard environment variable, named after the variable. Read it like any other environment variable.

import os

redis_host = os.environ["REDIS_HOST"]
redis_password = os.environ["REDIS_PASSWORD"]
const redisHost = process.env.REDIS_HOST;
const redisPassword = process.env.REDIS_PASSWORD;
var redisHost = Environment.GetEnvironmentVariable("REDIS_HOST");
var redisPassword = Environment.GetEnvironmentVariable("REDIS_PASSWORD");

Secret values are decrypted before injection, so your code receives the plaintext value at runtime.

Keep environments in sync

After you change a variable's value, an assignment, or a value set, the affected environments go out of sync. Sync each one to apply the change. Quix tracks which environments a given change affects, so you only sync where it matters, and the sync diff shows which group changed (including a switch from one value set to another).

Syncing redeploys the affected deployments

A running container reads its environment variables once at start, so it does not pick up a new value while running. When you sync the environment, Quix detects that the group's resolved values changed and redeploys the deployments that use it, so they restart with the new values — you don't need to redeploy them by hand. (The background out-of-sync check only flags the drift; applying it is the sync.)

Delete a group or value set

Deletes cascade:

  • Delete a value set — removes every variable's value for that set within the group, and deletes the assignments that selected it. Affected projects and environments must be re-assigned a value set.
  • Delete a group — removes the group, all its variables, and every assignment that referenced it. No project can resolve it afterwards.

The portal asks you to confirm before deleting. Because the delete cascades to variables and assignments across every project that uses the group, check which projects depend on it first. Re-creating a group with the same identifier does not restore previous assignments.

Deleting affects the next sync and the next deploy, not what is already running:

  • A running deployment keeps the environment variables it started with. A container reads its environment once, at start, and deleting a group does not restart it. The deployment runs on the old values until it is next redeployed.
  • The next sync flags the reference as unresolved. A deleted group reports NotFound; a group left with no assigned value set reports NotAssigned. See Template resolution and failure modes for each reason and its portal remediation.
  • The next deploy either fails or starts without the values. A required: true reference fails the deployment with an error; a reference that is not required is skipped, and the group's member keys are absent from the container — not set to an empty string, so your code sees an unset variable rather than an empty one. See Group-binding resolution and failure modes.

Renaming is safe by comparison. You can change a group's display name, and a value set's name, without breaking anything: quix.yaml resolves against the group's immutable identifier, and an assignment binds to the value set's own id rather than its name.

Full example

The two files below put this together — app.yaml defines the group references, and the quix.yaml deployment inherits them. Each VariableGroup reference expands at deploy time into every variable in its group, and the deployment's replicas field substitutes one member of the release-tiers group directly into the YAML.

app.yaml — in the order-processor application folder, references two groups:

name: order-processor
language: python
variables:
  - name: input
    inputType: InputTopic
    required: true
    defaultValue: orders
  - name: redis
    inputType: VariableGroup
    required: true
    variableGroupId: redis-config
    variableGroupName: Redis config
    variableGroupDescription: Shared Redis connection
    variables:
      - key: REDIS_HOST
        description: Redis server hostname
        defaultValue: localhost
        required: true
      - key: REDIS_PORT
        description: Redis server port
        defaultValue: "6379"
        required: true
      - key: REDIS_PASSWORD
        description: Redis auth password
        secret: true
        required: true
  - name: payments
    inputType: VariableGroup
    required: true
    variableGroupId: payment-provider
    variableGroupName: Payment provider
    variableGroupDescription: Payment provider credentials
    variables:
      - key: PAYMENT_API_KEY
        description: Payment provider API key
        secret: true
        required: true
      - key: PAYMENT_API_URL
        description: Payment provider base URL
        defaultValue: https://api.payments.example
        required: true
dockerfile: build/dockerfile
runEntryPoint: main.py

quix.yaml — the pipeline; the deployment references the application and inherits the group references above:

# Quix Project Descriptor
metadata:
  version: 2.0

deployments:
  - name: Order processor
    application: order-processor
    version: latest
    deploymentType: Service
    resources:
      limits:
        cpu: 200
        memory: 500
      replicas: {{release-tiers:REPLICA_COUNT}}
    # input, redis and payments are inherited from app.yaml (see note below)
Where are input, redis and payments?

The deployment references the order-processor application, so under descriptor version 2.0 it inherits the variables declared in that application's app.yaml — they aren't repeated here. Each environment's actual values come from the variable group's assigned value set, not from quix.yaml. See YAML 1.0 and 2.0 for the full inheritance and resolution model, including the resolved deployment the platform computes.

In this example:

  • The redis reference injects every variable in redis-config — for example REDIS_HOST, REDIS_PORT, REDIS_PASSWORD.
  • The payments reference injects every variable in payment-provider — for example PAYMENT_API_KEY, PAYMENT_API_URL. Variables the group marks as secret arrive decrypted at runtime.
  • {{release-tiers:REPLICA_COUNT}} takes the opposite route: the sync resolves it into the replicas field itself, so it configures the deployment rather than reaching the container as an environment variable. It needs release-tiers assigned to the project, just as the two references above need theirs.

If a REDIS_DB_INDEX variable is later added to redis-config, it reaches this deployment when it is next redeployed. Syncing the environment detects the group change and triggers that redeploy; no edit to app.yaml or quix.yaml is required.

Reference

This section is a precise specification of the quix.yaml and app.yaml shapes, the rules the platform enforces, and the resolution behavior — useful for power users and for tooling or AI assistants that generate the YAML.

quix.yaml variable fields

A deployment variable that references a group is an entry in deployments[].variables[] with these fields:

Field Required Type Meaning
name yes string A label for the reference, shown in the UI and error messages. Not injected as an environment variable.
inputType yes string Must be exactly VariableGroup to reference a group.
variableGroupId yes string The identifier of the variable group to inject. Resolution is keyed solely on this value.
required no boolean Default false. When true, the deployment fails to deploy if the group cannot be resolved. When false, an unresolved group is skipped.
variableGroupName no string Optional human-readable echo of the group's display name. Informational only — written by the portal for readability; does not affect resolution.
variableGroupDescription no string Optional human-readable echo of the group's description. Informational only.

app.yaml variable fields

On an application in app.yaml, a variable-group entry carries the same identifying fields as the quix.yaml reference, plus the group's nested variable schema under variables: (which a quix.yaml deployment never has):

Field Required Type Meaning
name yes string A label for the reference, shown in the UI and error messages. Not injected as an environment variable.
inputType yes string Must be exactly VariableGroup to reference a group.
variableGroupId yes string The identifier of the variable group to inject. Resolution is keyed solely on this value.
required no boolean Default false. When true, the deployment fails to deploy if the group cannot be resolved. When false, an unresolved group is skipped.
variableGroupName no string Optional human-readable echo of the group's display name. Informational only.
variableGroupDescription no string Optional human-readable echo of the group's description. Informational only.
variables no list The group's variable schema. app.yaml only — a quix.yaml deployment never lists these; it references the group by variableGroupId alone. Each entry has the fields below.

Each entry in the variables list:

Field Required Type Meaning
key yes string The variable's name — the environment-variable name injected into the container.
description no string Human-readable description of the variable.
defaultValue no string Default value for the variable.
secret no boolean When true, the value is encrypted at rest and hidden in the UI.
required no boolean When true, the variable must resolve to a value.

Template reference ({{ groupId:variableKey }})

A template reference is plain text inside a quix.yaml field, not a variables: entry — there is no inputType and no nested schema, just the {{ }} token itself.

Rule Detail
Form Exactly one : — groupId before it, variableKey after. No spaces immediately around the colon (spaces just inside {{ }} are trimmed and allowed).
groupId charset Same as a group's identifier: ^[A-Za-z0-9][A-Za-z0-9_-]*$, at most 254 characters.
variableKey charset Same as an environment-variable name: ^[a-zA-Z_][a-zA-Z0-9_]*$, at most 254 characters — no dots or hyphens.
Zero colons Parsed as a project variable reference instead — see Project variables.
Secret members Never resolved — see Pattern 1: substitute a group member.

Rules and constraints

  • A group identifier is immutable after the group is created. It must match ^[A-Za-z0-9][A-Za-z0-9_-]*$ (letters, digits, hyphens, underscores; not starting with a separator), at most 254 characters. Duplicate detection at creation is case-insensitive.
  • A reference's name is a label, never an injected environment variable. Injected names come from the variables inside the group.
  • A variable's name (the key inside a group) cannot contain spaces (recommended pattern [a-zA-Z_][a-zA-Z0-9_]*), because each becomes an OS environment-variable name.
  • A secret variable can be demoted to a plain value only by supplying a new value in the same edit; a demotion with no new value is rejected (the stored encrypted value is never exposed).
  • A project needs an assignment (project-level or environment-level) before a deployment can resolve a group.
  • The environment-level override wins over the project-level default when both are set.
  • Changing values or assignments marks affected environments out of sync; syncing the environment redeploys the deployments that use the group so they restart with the new values. (The background out-of-sync check only flags the drift; the sync applies it.)
  • Deleting a group or value set cascades to its variables and assignments.

Group-binding resolution and failure modes

At deploy time, for each VariableGroup reference:

Situation required: true required: false
variableGroupId is empty Deployment fails Logged and skipped
Group is not assigned to the environment Deployment fails Logged and skipped
Group resolves to a value set Every variable in that value set is injected as an environment variable Same

The value set used is the environment-level override if present, otherwise the project-level default.

Template resolution and failure modes

At sync time, for each {{ groupId:variableKey }} reference:

Reason Cause Portal remediation
NotFound The group does not exist. Create Group button
NotAssigned The group exists but has no value set assigned to this environment or its project. Assign Set button
ValueSetNotFound The assigned value set no longer exists in the group. Assign Set button
KeyNotFound variableKey does not exist in the assigned value set. Add variable button
SecretInTemplate The member exists but is marked Secret. Caption only, no button: "Edit YAML to remove this reference."
InvalidReference Either the reference is malformed (bad colon count, missing half, invalid characters), or — rarely — a well-formed reference that a resolver consistency check could not confirm. Malformed: caption "Edit YAML to correct this reference." Unconfirmed: no caption — the row reads "could not be checked against its variable group", and the hover adds "Try syncing again.", since the YAML itself is fine.

Each reason surfaces as a row in the sync dialog's Unresolved variable groups step, with the full detail available on hover in the Monaco editor.

How global variables compare with other variable types

Mechanism Scope Per-environment values Typical use
Environment variables Single deployment No Static, deployment-specific configuration
Project variables Single project Yes Per-environment scaling (CPU, MEMORY, REPLICAS) and project-scoped secrets
Global variables Organization-wide (via variable groups) Yes, through value sets Shared configuration consumed by multiple projects; one reference injects the whole group
Quix variables Platform-injected Read-only Built-in identifiers such as Quix__Workspace__Id

Glossary

Term Definition
Global variables The organization-scoped variable feature as a whole — variable groups, their value sets, and the variables inside them — shared across projects.
Variable group Organization-level container of related variables; the unit a project assigns. Identified by an immutable identifier.
Value set A named set of values within a group (e.g. DEV, PROD). Each variable has one value per value set.
Variable A key/value pair inside a group. Its name is the injected environment-variable name. May be a secret.
Assignment The link between a project and a group that selects which value set the project (or one of its environments) uses.
Override An environment-level assignment that replaces the project-level default value set for a single environment.