In Replit, environment variables are managed through the Secrets panel (Tools > Secrets), not through .env files or dotenv packages. To migrate from a .env-based setup, copy each variable into the Secrets panel using the Edit as .env bulk editor, delete the .env file, remove the dotenv dependency, and access values via process.env as usual. Replit provides predefined variables like REPLIT_DEPLOYMENT, REPL_ID, and REPLIT_DOMAINS. Deployment environments require secrets added separately in the Deployments pane.
Manage Environment Variables Securely in Replit for Node.js
This tutorial covers environment variable management in Replit with a focus on Node.js applications. If you are migrating from a local development setup that uses .env files and the dotenv package, this guide shows you how to transition to Replit's Secrets panel. We also cover predefined Replit variables, per-environment configuration strategies, and bulk editing for managing many variables at once. This is for intermediate Node.js developers who want a clean, secure environment variable workflow in Replit.
Prerequisites
- A Replit account with a Node.js project
- Existing environment variables you need to manage (API keys, database URLs, etc.)
- Basic familiarity with Node.js and process.env
- Optional: an existing .env file to migrate from
Step-by-step guide
Migrate your .env file to the Replit Secrets panel
Migrate your .env file to the Replit Secrets panel
If you have an existing .env file from local development or another platform, open it and copy its contents. Then open the Secrets panel from the Tools dock, click Edit as .env, and paste the contents. This bulk-imports all your environment variables at once. After importing, delete the .env file from your project and remove the dotenv package from your dependencies if present. In Replit, secrets are automatically injected as environment variables, so dotenv is unnecessary and can cause issues if it tries to load a nonexistent .env file.
1# Your existing .env file might look like this:2DATABASE_URL=postgresql://user:password@host:5432/mydb3OPENAI_API_KEY=sk-abc123def4564JWT_SECRET=my-super-secret-jwt-key5NODE_ENV=production6PORT=300078# Steps:9# 1. Copy the contents above10# 2. Open Tools > Secrets > Edit as .env11# 3. Paste and save12# 4. Delete the .env file from your project13# 5. Uninstall dotenv: npm uninstall dotenv14# 6. Remove require('dotenv').config() from your codeExpected result: All environment variables from your .env file are now in the Secrets panel, and the .env file and dotenv dependency are removed.
Remove dotenv references from your code
Remove dotenv references from your code
If your Node.js entry point includes require('dotenv').config() or import dotenv from 'dotenv', remove these lines. Replit injects secrets as environment variables automatically at runtime, so dotenv is redundant. Leaving dotenv in place can cause errors if it looks for a .env file that no longer exists, or worse, it can load stale values from an old .env file that conflicts with your Secrets panel values. Also remove the dotenv package from package.json to keep your dependencies clean.
1// BEFORE: remove this line2require('dotenv').config();34// AFTER: no import needed, process.env works directly5const dbUrl = process.env.DATABASE_URL;6const port = process.env.PORT || 3000;Expected result: Your code accesses process.env directly without any dotenv import or configuration.
Learn Replit's predefined environment variables
Learn Replit's predefined environment variables
Replit automatically sets several environment variables that you do not need to add to Secrets. REPLIT_DEPLOYMENT is set to '1' when the app runs in a deployed environment and is undefined in the workspace. REPLIT_DOMAINS contains the app's domain name. REPL_ID is the unique identifier for your Repl. REPL_SLUG is the project name. REPL_OWNER is your username. REPLIT_DB_URL is the connection URL for Replit's built-in key-value database. REPLIT_DEV_DOMAIN exists only in the workspace for development URLs. Use these in your code to make environment-aware decisions without adding custom secrets.
1// Detect environment2const isProduction = process.env.REPLIT_DEPLOYMENT === '1';34// Get the current domain (works in both workspace and deployment)5const domain = process.env.REPLIT_DOMAINS;67// Build URLs dynamically8const baseUrl = isProduction9 ? `https://${domain}`10 : `https://${process.env.REPLIT_DEV_DOMAIN}`;1112console.log(`Running at ${baseUrl} (${isProduction ? 'production' : 'development'})`);Expected result: Your code uses predefined variables to detect the environment and construct URLs dynamically.
Configure per-environment values for development and production
Configure per-environment values for development and production
Many services provide separate test and production credentials (like Stripe's test vs live keys). In Replit, you manage this by storing test credentials in workspace Secrets and production credentials in deployment Secrets. Your code uses REPLIT_DEPLOYMENT to select the correct configuration. You can also store both sets in workspace Secrets with different names (e.g., STRIPE_TEST_KEY and STRIPE_LIVE_KEY) and select the right one in code. The deployment Secrets override workspace Secrets for any matching key names.
1// config.js — per-environment configuration2const isProduction = process.env.REPLIT_DEPLOYMENT === '1';34module.exports = {5 db: {6 url: process.env.DATABASE_URL,7 ssl: isProduction,8 },9 stripe: {10 key: isProduction11 ? process.env.STRIPE_LIVE_KEY12 : process.env.STRIPE_TEST_KEY,13 },14 logging: {15 level: isProduction ? 'error' : 'debug',16 },17 server: {18 port: parseInt(process.env.PORT || '3000', 10),19 host: '0.0.0.0',20 },21};Expected result: Your application automatically uses the correct credentials based on whether it is running in the workspace or deployed.
Use bulk editing for managing many variables
Use bulk editing for managing many variables
When your project has many environment variables, individual entry is tedious. The Secrets panel supports two bulk editing modes. Click Edit as JSON to enter a JSON object where keys are variable names and values are the variable values. Click Edit as .env to enter standard KEY=VALUE format, one per line. Both modes let you add, update, or remove multiple variables at once. This is especially useful when copying configurations between projects or when a team member needs to set up the same environment. For teams managing complex configurations across multiple Replit projects, RapidDev can help establish standardized environment variable workflows.
1// JSON format for bulk editing2{3 "DATABASE_URL": "postgresql://user:pass@host:5432/db",4 "OPENAI_API_KEY": "sk-abc123",5 "JWT_SECRET": "long-random-string-here",6 "REDIS_URL": "redis://localhost:6379",7 "SMTP_HOST": "smtp.sendgrid.net",8 "SMTP_USER": "apikey",9 "SMTP_PASS": "SG.xxxxxxxxxxxx",10 "NODE_ENV": "production"11}Expected result: Multiple environment variables are created or updated in one operation through the bulk editor.
Verify secrets are loaded correctly in your application
Verify secrets are loaded correctly in your application
After setting up your environment variables, create a startup validation routine that checks all required variables are present. This runs when your app starts and immediately tells you if something is missing. Never log actual secret values. Instead, log whether each required secret is set (truthy) or missing. Run your app with the Run button and check the Console output. If any variables are missing, add them in the Secrets panel and restart.
1// startup-check.js — import at the top of your entry point2const REQUIRED = [3 'DATABASE_URL',4 'JWT_SECRET',5 'OPENAI_API_KEY',6];78const OPTIONAL = [9 'SMTP_HOST',10 'REDIS_URL',11];1213const isProduction = process.env.REPLIT_DEPLOYMENT === '1';14const context = isProduction ? 'Deployments > Secrets' : 'Tools > Secrets';1516const missing = REQUIRED.filter(key => !process.env[key]);17if (missing.length > 0) {18 console.error(`\nMissing required env vars (add in ${context}):`);19 missing.forEach(key => console.error(` - ${key}`));20 if (isProduction) process.exit(1);21}2223const missingOptional = OPTIONAL.filter(key => !process.env[key]);24if (missingOptional.length > 0) {25 console.warn(`\nOptional env vars not set: ${missingOptional.join(', ')}`);26}2728console.log(`Environment check passed (${isProduction ? 'production' : 'development'})`);Expected result: Your application logs a clear status of all environment variables at startup, with errors for missing required values.
Complete working example
1/**2 * Node.js application with secure environment variable management3 * All secrets stored in Replit Secrets panel (Tools > Secrets)4 * No .env files, no dotenv package5 */67// Startup validation (runs before anything else)8const isProduction = process.env.REPLIT_DEPLOYMENT === '1';9const envContext = isProduction ? 'Deployments > Secrets' : 'Tools > Secrets';1011const requiredVars = ['DATABASE_URL', 'JWT_SECRET'];12const missing = requiredVars.filter(v => !process.env[v]);13if (missing.length > 0) {14 console.error(`Missing env vars (add in ${envContext}): ${missing.join(', ')}`);15 if (isProduction) process.exit(1);16}1718// Application code19const express = require('express');20const app = express();2122const config = {23 port: parseInt(process.env.PORT || '3000', 10),24 dbUrl: process.env.DATABASE_URL,25 jwtSecret: process.env.JWT_SECRET,26 openaiKey: process.env.OPENAI_API_KEY || null,27 environment: isProduction ? 'production' : 'development',28 domain: process.env.REPLIT_DOMAINS || 'localhost',29};3031app.use(express.json());3233app.get('/api/health', (req, res) => {34 res.json({35 status: 'ok',36 environment: config.environment,37 features: {38 openai: !!config.openaiKey,39 },40 });41});4243app.get('/api/env-info', (req, res) => {44 // Safe: returns metadata, never actual secret values45 res.json({46 replId: process.env.REPL_ID,47 replSlug: process.env.REPL_SLUG,48 owner: process.env.REPL_OWNER,49 isDeployed: isProduction,50 domain: config.domain,51 });52});5354app.listen(config.port, '0.0.0.0', () => {55 console.log(`Server running on port ${config.port} (${config.environment})`);56 console.log(`Domain: ${config.domain}`);57});Common mistakes when setting environment variables in Replit safely
Why it's a problem: Keeping both a .env file and Secrets panel entries, causing confusion about which values are used
How to avoid: Delete the .env file entirely. Replit's Secrets panel is the single source of truth. The .env file is visible in public Repls and is not encrypted.
Why it's a problem: Using require('dotenv').config() in Replit
How to avoid: Remove dotenv. Run npm uninstall dotenv and delete the require/import statement. Replit injects secrets as environment variables automatically.
Why it's a problem: Using REPLIT_DEV_DOMAIN in production code
How to avoid: REPLIT_DEV_DOMAIN only exists in the workspace and is undefined in deployments. Use REPLIT_DOMAINS instead, which works in both environments.
Why it's a problem: Logging process.env to debug missing variables, which prints all secret values
How to avoid: Instead of console.log(process.env), check individual variables: console.log('DB set:', !!process.env.DATABASE_URL). This confirms presence without exposing values.
Why it's a problem: Expecting secrets added during runtime to be available without restarting
How to avoid: New secrets are not picked up by running processes. Click Stop then Run to restart your app, or run kill 1 in Shell to reload the environment.
Best practices
- Never use .env files or the dotenv package in Replit. Use the Secrets panel exclusively.
- Add deployment secrets separately from workspace secrets in the Deployments pane
- Validate all required environment variables at startup with clear error messages
- Use REPLIT_DEPLOYMENT to detect production vs development and select appropriate configurations
- Never log actual secret values. Log only whether they are set or missing.
- Use consistent naming conventions: UPPERCASE_WITH_UNDERSCORES for all environment variable names
- Use the bulk editor (Edit as JSON or Edit as .env) for efficient management of many variables
- Keep a documented list of all required and optional environment variables for your project
Still stuck?
Copy one of these prompts to get a personalized, step-by-step explanation.
I am migrating a Node.js project to Replit. It currently uses a .env file with dotenv. Show me how to: 1) Transfer all variables to Replit Secrets, 2) Remove dotenv cleanly, 3) Set up a config module that uses process.env with REPLIT_DEPLOYMENT for environment detection, 4) Configure separate development and production values.
Migrate my project from .env files to Replit Secrets. Remove all dotenv references, create a config.js module that validates required environment variables at startup, and set up environment detection using REPLIT_DEPLOYMENT. Show me which variables need to go in workspace Secrets vs deployment Secrets.
Frequently asked questions
No. Replit automatically injects secrets as environment variables at runtime. The dotenv package is unnecessary and can cause issues if it looks for a .env file that does not exist. Remove it with npm uninstall dotenv.
Workspace secrets are available when you click Run in the editor. Deployment secrets are used by your deployed app (Autoscale, Reserved VM, Scheduled). They are configured separately and can have different values, such as test vs production API keys.
Replit sets REPLIT_DEPLOYMENT (1 in deployed apps), REPLIT_DOMAINS (app domain), REPL_ID, REPL_SLUG, REPL_OWNER, REPLIT_DB_URL (key-value DB), and REPLIT_DEV_DOMAIN (workspace only, not in deployments).
Store test credentials in workspace Secrets and production credentials in deployment Secrets. Use process.env.REPLIT_DEPLOYMENT === '1' in your code to detect the environment and select the correct configuration.
Yes. Open the Secrets panel, click Edit as .env, and paste the contents of your .env file. All variables are imported at once. Then delete the .env file from your project.
Yes. RapidDev helps teams establish consistent environment variable conventions, set up validation frameworks, and manage multi-project configurations. They can create standardized config modules and documentation for your team's Replit workflow.
Running processes do not automatically pick up new secrets. Restart your app by clicking Stop then Run, or run kill 1 in Shell. Also verify you are checking the correct Secrets location: workspace Secrets for development, deployment Secrets for deployed apps.
Yes. You can set non-sensitive environment variables under [run.env] in the .replit file. However, never put API keys or sensitive values there since the .replit file is part of your source code and visible in public Repls. Use the Secrets panel for all sensitive values.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation