# How to Manage Multiple Environments in Retool

- Tool: Retool
- Difficulty: Intermediate
- Time required: 20-25 min
- Compatibility: Retool Cloud and Self-hosted
- Last updated: March 2026

## 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.

## 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.

## Before you start

- 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.

```
// Concept illustration (not code — done in UI):
// Resource: PostgreSQL - Main DB
// 
// Staging environment:
//   Host: staging-db.yourcompany.com
//   Database: app_staging
//   Username: retool_staging
//   Password: [staging password]
//
// Production environment:
//   Host: prod-db.yourcompany.com  
//   Database: app_production
//   Username: retool_prod
//   Password: [production password]
//
// Same resource name, completely different connections.
// Queries in the app use the same resource name; Retool routes
// 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.

```
// Show environment banner when NOT in production:
// Text component content:
{{ retoolContext.environment !== 'production' 
   ? '⚠️ ' + retoolContext.environment.toUpperCase() + ' ENVIRONMENT — Not production data'
   : '' }}

// Text component Hidden property (hide banner in production):
{{ retoolContext.environment === 'production' }}

// Disable a destructive button in production:
// Button Disabled property:
{{ retoolContext.environment === 'production' }}

// JS Query: behave differently by environment:
const isProd = retoolContext.environment === 'production';
const limit = isProd ? 1000 : 50;

return await fetchOrders.trigger({
  additionalScope: { limit }
});
```

**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.

```
// Config var: API_BASE_URL
// Staging:    https://api.staging.yourcompany.com
// Production: https://api.yourcompany.com

// Config var: MAX_BATCH_SIZE  
// Staging:    10
// Production: 500

// In app queries:
const apiBase = retoolContext.configVars.API_BASE_URL;
const batchSize = parseInt(retoolContext.configVars.MAX_BATCH_SIZE) || 100;

console.log(`Running in ${retoolContext.environment}: ${apiBase}`);

// SQL with environment-aware limit:
SELECT * FROM orders 
WHERE status = 'pending'
LIMIT {{ 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 code example

File: `JS Query: environmentDiagnostics`

```javascript
// JS Query: environmentDiagnostics
// Run this to verify environment setup is correct
// Useful during initial environment configuration

const env = retoolContext.environment;
const configVars = retoolContext.configVars;

const diagnostics = {
  currentEnvironment: env,
  isProduction: env === 'production',
  isStaging: env === 'staging',
  
  // Config var presence check
  configVarChecks: {
    API_BASE_URL: configVars.API_BASE_URL ? 'SET: ' + configVars.API_BASE_URL : 'NOT SET',
    MAX_BATCH_SIZE: configVars.MAX_BATCH_SIZE ? 'SET: ' + configVars.MAX_BATCH_SIZE : 'NOT SET (will use default)',
    FEATURE_FLAG_X: configVars.FEATURE_FLAG_X || 'NOT SET',
  },
  
  // Safety checks
  safetyWarnings: [],
  timestamp: new Date().toISOString()
};

// Safety: warn if running destructive query config in wrong env
if (env === 'production' && configVars.ALLOW_BULK_DELETE === 'true') {
  diagnostics.safetyWarnings.push('CAUTION: Bulk delete is enabled in production');
}

if (env !== 'production' && configVars.API_BASE_URL && 
    !configVars.API_BASE_URL.includes('staging')) {
  diagnostics.safetyWarnings.push('WARNING: Non-staging environment but API URL does not contain "staging" — verify this is correct');
}

return diagnostics;
```

## Common mistakes

- **Editing the app in Production environment in the editor and accidentally running destructive queries against production data** — undefined Fix: 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.
- **Publishing a release while testing in Staging, assuming the release will only affect staging users** — undefined Fix: 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.
- **Using the same database connection for both environments and relying on conditional queries to avoid touching production tables** — undefined Fix: 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

## 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.

---

Source: https://www.rapidevelopers.com/retool-tutorial/how-to-manage-multiple-environments-in-retool
© RapidDev — https://www.rapidevelopers.com/retool-tutorial/how-to-manage-multiple-environments-in-retool
