Skip to main content
RapidDev - Software Development Agency
retool-tutorial

How to Manage Multiple Environments in Retool

Retool environments let you run the same app against different backends (staging DB, production DB) without code changes. Create environments in Settings → Environments. Then configure each resource to use different credentials per environment. In the editor toolbar, switch the Environment selector to test against staging or production. Use `{{ retoolContext.environment }}` in app logic to conditionally behave differently per environment.

What you'll learn

  • How Retool's environment system works and how to create staging and production environments
  • How to connect the same resource (database, API) to different staging vs. production credentials
  • How to use {{ retoolContext.environment }} to write environment-conditional app logic
  • How to switch environments in the editor for testing before deploying
  • How to test safely in staging without risking production data
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Intermediate8 min read20-25 minRetool Cloud and Self-hostedLast updated March 2026RapidDev Engineering Team
TL;DR

Retool environments let you run the same app against different backends (staging DB, production DB) without code changes. Create environments in Settings → Environments. Then configure each resource to use different credentials per environment. In the editor toolbar, switch the Environment selector to test against staging or production. Use `{{ retoolContext.environment }}` in app logic to conditionally behave differently per environment.

Quick facts about this guide
FactValue
ToolRetool
DifficultyIntermediate
Time required20-25 min
CompatibilityRetool Cloud and Self-hosted
Last updatedMarch 2026

Retool Environments: Safe Staging and Production Separation

Retool's environment system lets one app run against completely different backend resources depending on whether it's in staging or production mode. The app code is identical — only the underlying data source changes. This is critical for testing: you can validate queries against your staging database before allowing them to touch production data.

Environments in Retool work at the resource level. A 'PostgreSQL - Orders' resource can have different host, username, and password values for staging vs. production. When the environment selector shows 'Staging', all queries using that resource connect to the staging database. Switch to 'Production', and the same queries connect to production.

Beyond resources, apps can read the current environment via `{{ retoolContext.environment }}` to conditionally show banners, limit actions, or log differently per environment.

Prerequisites

  • Admin access to Retool (required to create environments and configure resources)
  • Two sets of database/API credentials: one for staging, one for production
  • Understanding of which Retool resources need environment-specific configuration
  • Retool plan that supports multiple environments (Team plan or above)

Step-by-step guide

1

Create Retool environments

Go to Settings (top-right user menu) → Environments. By default, Retool provides a 'Production' environment. Click 'Add Environment' to create a staging environment. Give it a name like 'Staging' or 'Development'. You can create multiple environments (e.g., Dev, QA, Staging, Production). The order of environments in the list matters — the topmost is the default for new apps. Drag environments to reorder them. Mark one as the 'Default' environment (usually Production for safety).

Expected result: A new 'Staging' environment appears in Settings → Environments list.

2

Configure resources with per-environment credentials

The key benefit of environments is per-environment resource configuration. Go to Settings → Resources → select a resource (e.g., your PostgreSQL database) → Edit. In the resource editor, you'll see credential fields. Look for an Environment selector at the top — switch between environments to set different credentials for each. For your staging database, enter staging credentials. Switch to Production and enter production credentials. Save each environment's configuration separately.

typescript
1// Concept illustration (not code — done in UI):
2// Resource: PostgreSQL - Main DB
3//
4// Staging environment:
5// Host: staging-db.yourcompany.com
6// Database: app_staging
7// Username: retool_staging
8// Password: [staging password]
9//
10// Production environment:
11// Host: prod-db.yourcompany.com
12// Database: app_production
13// Username: retool_prod
14// Password: [production password]
15//
16// Same resource name, completely different connections.
17// Queries in the app use the same resource name; Retool routes
18// to the right backend based on the active environment.

Expected result: The resource has different credentials saved for each environment. Switching the environment selector changes which database queries execute against.

3

Switch environments in the editor

In the Retool editor toolbar, look for the Environment selector — it's typically a dropdown showing the current environment name (e.g., 'Staging' or 'Production'). Click it to switch between environments. When you switch to Staging, all queries in the app execute against staging resources. Run your queries in Preview mode to verify they return staging data. Switch to Production to test against production resources (be careful — queries that write data will affect real production). The environment selector state is per-editor-session, not saved with the app. Users who open the app URL always run in the environment that matches their organization's default (usually Production).

Expected result: After switching to Staging, query results show staging database data. Table row counts, test data, and recent changes reflect the staging environment.

4

Use retoolContext.environment in app logic

Read the current environment name in any `{{ }}` expression or JS query using `retoolContext.environment`. This returns the environment name string (e.g., 'staging', 'production', or whatever you named your environment). Common uses: showing an environment banner, disabling destructive actions in production without testing, and conditional query logic.

typescript
1// Show environment banner when NOT in production:
2// Text component content:
3{{ retoolContext.environment !== 'production'
4 ? '⚠️ ' + retoolContext.environment.toUpperCase() + ' ENVIRONMENT — Not production data'
5 : '' }}
6
7// Text component Hidden property (hide banner in production):
8{{ retoolContext.environment === 'production' }}
9
10// Disable a destructive button in production:
11// Button Disabled property:
12{{ retoolContext.environment === 'production' }}
13
14// JS Query: behave differently by environment:
15const isProd = retoolContext.environment === 'production';
16const limit = isProd ? 1000 : 50;
17
18return await fetchOrders.trigger({
19 additionalScope: { limit }
20});

Expected result: The environment banner appears when editors test in non-production environments, and is hidden for end users in production.

5

Create environment-specific configuration variables

For settings that differ between environments (API base URLs, feature flags, rate limits), use Configuration Variables (configVars) with per-environment values. This is separate from resource credentials — configVars handle non-connection configuration. Go to Settings → Configuration Variables → Create Variable. Assign different values to the Staging and Production environments for the same variable name. The app accesses them via `{{ retoolContext.configVars.VARIABLE_NAME }}` and automatically gets the environment-appropriate value.

typescript
1// Config var: API_BASE_URL
2// Staging: https://api.staging.yourcompany.com
3// Production: https://api.yourcompany.com
4
5// Config var: MAX_BATCH_SIZE
6// Staging: 10
7// Production: 500
8
9// In app queries:
10const apiBase = retoolContext.configVars.API_BASE_URL;
11const batchSize = parseInt(retoolContext.configVars.MAX_BATCH_SIZE) || 100;
12
13console.log(`Running in ${retoolContext.environment}: ${apiBase}`);
14
15// SQL with environment-aware limit:
16SELECT * FROM orders
17WHERE status = 'pending'
18LIMIT {{ parseInt(retoolContext.configVars.MAX_BATCH_SIZE) || 100 }}

Expected result: The same query automatically uses staging API URL in staging and production API URL in production.

6

Test a new release in staging before deploying to production

The best practice workflow for environment management: 1. Build and test the app in the editor with Staging environment selected 2. Preview the app (Preview button) in Staging — verify queries work, data loads, UI functions correctly 3. Switch the editor to Production environment — do a read-only review (don't submit forms or trigger writes) 4. Create a release (Manage Releases → Create Release) — releases are environment-agnostic 5. Have a colleague test the production app URL (not the editor) before announcing the update 6. If issues found: fix in editor in staging, re-verify, publish a new release This workflow catches environment-specific bugs before real users encounter them.

Expected result: Releases are only published after full staging validation, reducing production incidents.

Complete working example

JS Query: environmentDiagnostics
1// JS Query: environmentDiagnostics
2// Run this to verify environment setup is correct
3// Useful during initial environment configuration
4
5const env = retoolContext.environment;
6const configVars = retoolContext.configVars;
7
8const diagnostics = {
9 currentEnvironment: env,
10 isProduction: env === 'production',
11 isStaging: env === 'staging',
12
13 // Config var presence check
14 configVarChecks: {
15 API_BASE_URL: configVars.API_BASE_URL ? 'SET: ' + configVars.API_BASE_URL : 'NOT SET',
16 MAX_BATCH_SIZE: configVars.MAX_BATCH_SIZE ? 'SET: ' + configVars.MAX_BATCH_SIZE : 'NOT SET (will use default)',
17 FEATURE_FLAG_X: configVars.FEATURE_FLAG_X || 'NOT SET',
18 },
19
20 // Safety checks
21 safetyWarnings: [],
22 timestamp: new Date().toISOString()
23};
24
25// Safety: warn if running destructive query config in wrong env
26if (env === 'production' && configVars.ALLOW_BULK_DELETE === 'true') {
27 diagnostics.safetyWarnings.push('CAUTION: Bulk delete is enabled in production');
28}
29
30if (env !== 'production' && configVars.API_BASE_URL &&
31 !configVars.API_BASE_URL.includes('staging')) {
32 diagnostics.safetyWarnings.push('WARNING: Non-staging environment but API URL does not contain "staging" — verify this is correct');
33}
34
35return diagnostics;

Common mistakes

Why it's a problem: Editing the app in Production environment in the editor and accidentally running destructive queries against production data

How to avoid: Set the editor default to Staging and only switch to Production for read-only verification. Add a Disabled property to destructive buttons: {{ retoolContext.environment === 'production' && isEditorMode }} — though note isEditorMode isn't a built-in; you'll need to use a configVar for editor-mode detection.

Why it's a problem: Publishing a release while testing in Staging, assuming the release will only affect staging users

How to avoid: Releases in Retool are environment-agnostic — they capture the app code, not the environment selector state. When published, the release runs against whatever environment each user is in (usually Production by default). Always verify the app works correctly in Production environment before publishing.

Why it's a problem: Using the same database connection for both environments and relying on conditional queries to avoid touching production tables

How to avoid: Configure separate resource credentials per environment. Never route both staging and production through the same database connection — a query bug in staging should not be able to affect production tables.

Best practices

  • Always test in Staging with Preview mode before publishing a release — never test by publishing directly to production
  • Show a visible environment indicator (banner, colored header) in non-production environments so editors never accidentally submit production data while in staging mode
  • Use read-only database credentials in staging to prevent test code from accidentally modifying production data if the wrong environment is selected
  • Configure configVars for ALL environments — a missing configVar in production returns undefined and causes runtime errors
  • Make the production environment the default so users who open the app without selecting an environment see real data
  • Document which resources are environment-specific and which are shared (e.g., a logging resource might be the same in all environments)
  • Use the staging environment for load testing or large data imports that could slow down or corrupt production databases

Still stuck?

Copy one of these prompts to get a personalized, step-by-step explanation.

ChatGPT Prompt

I'm setting up Retool for my team with staging and production environments. Explain: (1) how to create staging and production environments in Retool Settings, (2) how to configure the same PostgreSQL resource with different credentials for each environment, (3) how to use retoolContext.environment in app expressions to show a staging warning banner, (4) how to test an app safely in staging before releasing to production, and (5) what configVars per-environment values are and how to use them.

Retool Prompt

Configure this Retool app for multi-environment support: (1) add a Text component at the top that shows '⚠️ STAGING ENVIRONMENT' with yellow background when retoolContext.environment !== 'production', (2) add Hidden: {{ retoolContext.environment === 'production' }} to the banner, (3) add a JS query called environmentDiagnostics that returns retoolContext.environment and all configVars, (4) disable the 'Delete Selected' button when in production using the Disabled property.

Frequently asked questions

Do Retool releases apply to all environments or just the one I'm testing in?

Retool releases are environment-agnostic — they capture the app code, not the environment state. When you publish a release, it becomes the active version for all users regardless of their environment. Users typically run in Production by default. Test in staging first, but remember that your release will affect all environments when published.

Can I give some users access to the staging environment and others only production?

Yes. In Settings → Environments, you can configure which Retool user groups have access to each environment. Restrict staging access to developers/admins and keep regular users in production only. This prevents non-technical users from accidentally running staging resources.

Can retoolContext.environment be spoofed or changed by end users?

No. The environment is determined server-side by Retool based on the organization's environment configuration, not by client-side user input. End users cannot change the environment through the UI (they don't see the environment selector) and cannot manipulate it in browser DevTools. It's a trusted value.

RapidDev

Talk to an Expert

Our team has built 600+ apps. Get personalized help with your project.

Book a free consultation

Learning is great. Shipping is faster with help.

Our engineers have built 600+ apps on Retool and the tools around it. If your project needs to be live sooner than your learning curve allows — book a free consultation.

Book a free consultation

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.