Skip to main content

Use Environment Variables

Goal​

Declare a setting once in your solution — an API address, a mailbox, a feature switch — and let Dev, Test, and Production each answer it their own way, without editing the solution after every import.

Why this exists​

A solution promoted from Dev to Test to Production is supposed to be the same solution. And yet some of what it does has to differ per environment: the service it calls, the address it sends from, whether a feature is switched on.

Without environment variables there are only two ways to express that, and both are bad. You can edit components after every import — which makes your environments quietly diverge, and hides the divergence. Or you can hard-code the Dev value and remember to change it — which works right up until the day nobody remembers.

An environment variable splits the setting in two:

  • The declaration — its name, type, description, and default. This belongs to the solution and travels with it.
  • The value — this environment's answer. It belongs to the environment and never leaves it. Exporting the solution does not carry it, and importing the solution does not overwrite it.

Prerequisites​

  • You are signed in as a maker, with a solution and an environment selected.

Steps​

Declare a variable (usually in Dev)​

  1. Open your solution and choose Environment variables in the left navigation.
  2. Select New.
  3. Enter a display name (for example, Invoice API URL). The logical name fills in below with your publisher's prefix applied — invoice_api_url becomes par_invoice_api_url.
  4. Choose a type: Text, Number, Boolean (true/false), or JSON. Any value set for the variable is checked against it, in whichever environment it is typed.
  5. Write a description. This is worth more effort here than on most things you build: whoever sets the value in Production is often not you, and a bare name rarely says what a correct value looks like.
  6. Optionally enter a default value — what is used wherever an environment has set none. Leave it empty for something with no sensible default (a secret, a per-customer address), so that an unset variable is visibly unset rather than quietly wrong.
  7. Select Save.

Set this environment's value (in each environment)​

  1. Open Environment variables, select the variable's row (or select it and choose Set value).
  2. Enter the value this environment should use, and select Save.
  3. To go back to the declared default, empty the box and save. That is a decision, and it is the only way back once a value has been set.

The Effective value column tells you which of three states each variable is in:

It readsIt means
a valuethis environment set it
a value, then (using the default)nothing was set here; the solution's default applies
Not setneither — nothing answers this variable here, and anything reading it will find nothing

Not set is the state to clear before go-live.

Read a variable from a plugin step​

In a BS Lang plugin step, getEnvironmentVariable("par_invoice_api_url") returns the effective value for the environment the write is happening in. That is what lets one script be correct everywhere: it names the setting rather than the address.

An unset variable reads as an empty string, so a script that needs one should say so rather than carry on:

if (getEnvironmentVariable("par_invoice_api_url") == "") {
throwValidationError("The invoice API URL is not configured in this environment.");
}

A missing setting is a configuration mistake, not a value — failing loudly here is much kinder than failing obscurely later.

What happens behind the scenes​

The declaration is a solution component like a table or an option set: it is validated against a published schema, it belongs to your publisher's namespace, and it travels in the solution package. The value is stored against the environment and is never written into a package.

On import into another environment:

  • a variable arriving for the first time lands with its declared default and no value;
  • a variable that is already there has its declaration updated — a renamed label, a changed default, a corrected description — and its value left exactly as that environment set it.

That second rule is the one the whole feature exists for. Promoting a solution to Production must never silently repoint Production at Dev's endpoint.

Uninstalling the solution removes its variables, values included — at that point there is nothing left to configure.

Troubleshooting​

  • "'…' is not a valid Number value." (or Boolean/JSON) — the value does not match the declared type. It is checked where you type it, on purpose, rather than wherever it is later read: a script discovering it would fail far away from the mistake, and probably in Production.
  • I changed the type and my value disappeared. — the value no longer fitted the new type, so it was cleared rather than kept as something nothing can read. The variable falls back to its default and reads as unset, which is visible. Set it again.
  • I imported the solution and Production still shows the old value. — that is the intended behaviour: an import never overwrites an environment's own value. Change it on the Set value drawer in Production.
  • My default value reached Production but my Dev value did not. — also intended. The default is part of the declaration and travels; the value is the environment's and does not.
  • A script reads an empty string. — the variable is declared but unset in this environment, or the name is misspelled. Check the Effective value column; Not set tells the two apart from a typo, which will not appear in the list at all.
  • "An environment variable named … already exists in this environment." — logical names are unique within an environment. Choose another, or edit the existing one.