Environments and Variables — Global, Collection, Environment

9 min read

The single most powerful organisational feature in Postman is variables. They turn 50 requests with hardcoded https://staging.example.com into 50 requests with {{baseUrl}} — and one dropdown switches the whole suite from staging to production. This lesson covers Postman's five variable scopes, how they override each other, where to put which value, and how to set variables from a test script. By the end, your JSONPlaceholder API Tests collection will be variable-driven and ready to run against any environment.

What variables are for

A variable is a named value that Postman substitutes wherever you reference it with double curly braces:

{{baseUrl}}/users/{{userId}}

When the request is sent, Postman replaces {{baseUrl}} with https://jsonplaceholder.typicode.com and {{userId}} with 1. The substitution works in the URL, headers, body, params, scripts — anywhere text goes.

Why bother?

  • No hardcoded URLs. Switch between dev, staging, and prod with a dropdown.
  • No leaked secrets. Tokens live in environment variables, not in request files committed to Git.
  • Less duplication. Change a base URL in one place; 80 requests update.
  • Test setup. A login test extracts the auth token; every subsequent request uses {{authToken}}.

The cost is one ergonomic friction (curly braces) for one giant maintenance win.

The five scopes

Postman has five variable scopes. They differ in lifetime (how long the value persists) and breadth (which requests can see it).

Postman resolves variables top-to-bottom in this order. Local wins over Data, Data wins over Environment, Environment wins over Collection, Collection wins over Global. If {{baseUrl}} is defined as a global and an environment variable, the environment value is what gets used.

The practical heuristic for choosing a scope:

  • Global — values you genuinely want everywhere, regardless of which collection or environment is active. Almost nothing belongs here. New users overuse globals; later they regret it.
  • Collection — values that belong to one collection but don't change between environments. E.g. an API path prefix or a default page size.
  • Environment — values that do change between environments. {{baseUrl}}, {{apiKey}}, {{testUserEmail}}. This is where most of your variables should live.
  • Data — only when running with the Collection Runner over a CSV/JSON file (Chapter 4). Each row becomes one set of data variables.
  • Local — set inside a script for the duration of one request. pm.variables.set("now", Date.now()) inside a pre-request script.

Creating an environment

An environment is a named bag of variables you can switch on and off.

  1. Click the Environments tab in the sidebar (or the eye icon in the top-right → + Add next to Environments).
  2. Click + at the top → name it JSONPlaceholder.
  3. Add variables, one per row. For each, fill in:
    • Variable — the name (no curly braces). Use snake_case or camelCase consistently — baseUrl, authToken.
    • Typedefault or secret. Pick secret for tokens and passwords; Postman masks them in the UI.
    • Initial value — synced to the cloud and shared with your team if you push the environment.
    • Current value — local to your machine, never synced.

Sample setup for JSONPlaceholder:

VariableTypeInitialCurrent
baseUrldefaulthttps://jsonplaceholder.typicode.comhttps://jsonplaceholder.typicode.com
testUserIddefault11

Save. Then click the environment dropdown in the top-right of the Postman window and select JSONPlaceholder. Now {{baseUrl}} and {{testUserId}} resolve when used in any request.

Initial value vs current value — the gotcha

Every variable has both:

  • Initial value — what teammates see when they fork the environment. Synced to the Postman cloud.
  • Current value — what your requests actually use. Stays local to your machine.

The rule: never put a real secret in Initial value. If you do, anyone you share the environment with sees it (and Postman may sync it through the cloud). Put placeholders in Initial (<paste your token>) and the real value in Current.

When values mysteriously won't update — "I set the token but it's not working!" — it's almost always because you set the Initial value but Postman is using the Current value. The eye-icon quick-view shows both side by side; check which one has the right value.

Switching environments

In the top-right corner there's a dropdown that says No Environment by default. Click it; pick JSONPlaceholder (or Dev, Staging, Prod once you create more). The active environment colours the dropdown and applies to every request. The eye icon next to the dropdown opens a quick-view of every variable in scope right now.

Want to test the same collection against Production? Create a Prod environment with baseUrl = https://api.real-shop.com and authToken = <prod token>. Switch the dropdown. Re-run. Same requests, different target.

Using variables in requests

Curly braces work anywhere:

  • URL bar{{baseUrl}}/users/{{userId}}
  • HeadersAuthorization: Bearer {{authToken}}
  • Body{ "email": "{{testEmail}}", "password": "{{testPassword}}" }
  • Params tab — values can be {{tenantId}}
  • Pre-request and Tests scripts — read with pm.environment.get("baseUrl"), write with pm.environment.set("authToken", "...")

Hover over a {{var}} reference in the URL bar and Postman shows the resolved value in a tooltip — instant sanity check before sending.

Setting variables from a test script

The most common pattern in real test suites: extract a value from a response and stash it for later requests.

// Tests tab on POST /login
const response = pm.response.json();
pm.environment.set("authToken", response.token);
pm.collectionVariables.set("userId", response.user.id);

That snippet, after a login request, stores authToken in the active environment and userId in the collection. Any subsequent request can use {{authToken}} or {{userId}} and it Just Works. We'll wire this up properly in Chapter 3 (chaining requests with variables).

The choice between pm.environment.set and pm.collectionVariables.set is just where the value should live — environment if it's environment-specific (a token tied to staging), collection if it's a general fact (a userId you keep using).

Inspecting active variables

Click the eye icon in the top-right corner. A panel slides out showing every variable currently in scope, grouped by their level. Useful when a {{var}} reference is producing the wrong value — you can see at a glance whether it's coming from Environment, Collection, or Global.

⚠️ Common mistakes

  • Putting secrets in Initial value. Initial syncs to the cloud and is visible to teammates. Always put real tokens and passwords in Current value only, with a placeholder in Initial.
  • Hardcoding the same value as a Global and an Environment variable. When the values get out of sync (and they will), the environment wins, but it's confusing. Pick one scope per variable and stick to it.
  • Using pm.globals.set when you meant pm.environment.set. Globals leak across collections and stay around forever. Default to environment-scoped writes; reach for globals only when you genuinely want cross-collection state.

🎯 Practice task

Make your collection environment-driven. 25-30 minutes.

  1. Create a new environment called JSONPlaceholder. Add two variables: baseUrl = https://jsonplaceholder.typicode.com and testUserId = 1. Save.
  2. Activate the environment using the top-right dropdown.
  3. Open every request in your JSONPlaceholder API Tests collection. Replace the hardcoded base URL with {{baseUrl}} (e.g. {{baseUrl}}/users/1). On GET User by ID, replace the 1 with {{testUserId}}. Save each request.
  4. Re-run all requests. They should still work. Hover over {{baseUrl}} in the URL bar to confirm it resolves correctly.
  5. Create a second environment called JSONPlaceholder Mirror. Set baseUrl = https://my-json-server.typicode.com/typicode/demo. Save and switch to it.
  6. Re-send any request. Note the URL is now hitting a different host with the same paths — that's the power of variables.
  7. On any GET request, paste this into the Tests tab:
    pm.test("Response is JSON", () => {
      pm.response.to.have.header("Content-Type", "application/json; charset=utf-8");
    });
    const data = pm.response.json();
    if (Array.isArray(data) && data.length > 0) {
      pm.collectionVariables.set("firstId", data[0].id);
    }
    Send. Open the eye-icon quick-view. Confirm firstId now has a value. (Don't worry about the test syntax — Chapter 3 covers this in depth.)
  8. Stretch: create three environments — Dev, Staging, Prod — each with a different baseUrl. Even if dev and staging point at the same JSONPlaceholder URL, the act of switching between them is the muscle memory you'll use in real work.

You can now make one collection run against any number of environments. The next lesson covers the other half of the equation: getting collections in and out of Postman — for backups, version control, and team sharing.

// tip to track lessons you complete and pick up where you left off across devices.