Pathubs Logo Mark
PATHUBSFREE CAREER ROADMAPS
HomeExploreDiscoverCompare ⚖️My Progress 📊Support
Student Support & Feedback

Have Questions or Need Help?

Have questions, feedback, or suggestions for new roadmaps and interactive tools? Reach out to our team — we review every message to make practical learning better for everyone.

supportpathubs@gmail.com Official Telegram Support (@PathubsSupport)
Pathubs

100% Free, Zero-Paywall Tech Career Roadmaps, In-Depth Practical Content, and Live Interactive Virtual Labs for Learners Worldwide.

Popular Careers

  • Frontend Development
  • Backend Development
  • AI & LLM Engineering
  • Full Stack Web Dev
  • Data Analytics

Platform Tools

  • Career Discovery Quiz
  • Compare Careers

Contact & Info

  • About Us
  • supportpathubs@gmail.com
  • Support Pathubs

© 2026 Pathubs. All Rights Reserved. Structured learning, practical content, and hands-on practice for learners worldwide.

AboutPrivacy PolicyTerms & ConditionsSitemapRobots
HomeResourcesFull Stack: Environment Variables
Full Stack Web Development 12-Factor App Config OWASP Secrets Security Node.js 20.6+ & Next.js

Environment Variables in Full Stack Web Development

Master how modern web applications consume configuration and secrets from their host environments. Learn the strict trust boundary separating private server-side variables from public client bundles, and discover why environment variables are not automatically secure without rigorous isolation.

THE CORE PRINCIPLE: Source code should never contain hardcoded secrets or environment-specific configuration. Inject configuration at runtime via the host environment, and treat any variable sent to the browser as completely public.

Standards: The Twelve-Factor App (Factor III: Config)
Architecture: Node.js Server vs Next.js NEXT_PUBLIC_ Inlining
Est. Time: 50–65 Minutes
Curriculum Outline (9 Core Sections)
01. What Are Env Vars?02. Env Vars vs Hardcoding03. Server vs Client Boundary🔥 04. Live Environment Playground05. .env & .env.example Files06. Git + Secrets Security07. Development vs Production🔥 08. Real-World Debugging Lab🎯 09. Final Mini Challenge

01. What Are Environment Variables?

Decoupling dynamic configuration from executable code

An environment variable is a dynamic key-value pair provided to an application from the operating system or container runtime when the process boots, rather than being hardcoded directly into source files.

Configuration

Non-sensitive operational settings that change between deployment targets.

• PORT=3000 or PORT=8080
• NODE_ENV=production
• LOG_LEVEL=debug

Secrets

Sensitive credentials that grant administrative access to systems or cloud services.

• DATABASE_URL=postgres://...
• API_KEY=sk_live_948...
• JWT_SECRET=super-secret-key

Public Client Values

Values safely exposed to the browser to direct frontend network traffic.

• NEXT_PUBLIC_API_URL
• NEXT_PUBLIC_ANALYTICS_ID
• NEXT_PUBLIC_APP_NAME

Real-World Full Stack Example: The Database URL
In development, your backend connects to a local container: postgresql://dev:dev@localhost:5432/myapp. In production, it connects to a multi-region cloud cluster with SSL: postgresql://admin:StrongPass@db.prod.internal:5432/myapp?sslmode=require.

Because the application reads process.env.DATABASE_URL, the exact same code executes cleanly in Development, Testing, Staging, and Production without changing a single line of code!

02. Environment Variables vs Hardcoding

Eliminating critical security vulnerabilities from source code

Hardcoded in Source Code (❌ Dangerous)

// paymentService.js
// ❌ WRONG: Secret baked directly into code
const STRIPE_KEY = "sk_live_9481948194819481948";
const DB_URL = "postgres://admin:Password123@prod.db:5432";

export async function processPayment(amount) {
  const stripe = new Stripe(STRIPE_KEY);
  return stripe.charges.create({ amount });
}

Injected via Environment Variable (✅ Secure)

// paymentService.js
// ✅ CORRECT: Injected from runtime host
const STRIPE_KEY = process.env.STRIPE_SECRET_KEY;
const DB_URL = process.env.DATABASE_URL;

export async function processPayment(amount) {
  if (!STRIPE_KEY) {
    throw new Error("FATAL: STRIPE_SECRET_KEY is missing!");
  }
  const stripe = new Stripe(STRIPE_KEY);
  return stripe.charges.create({ amount });
}
Crucial Security Fact: Env Vars Are NOT Magically Secure
Environment variables are an injection mechanism, not an encryption vault. If you print console.log(process.env) in an unauthenticated endpoint or expose them to client-side bundles, they leak immediately. Their safety depends entirely on where and how your application accesses them.

03. Server-Side vs Client-Side Variables

The critical trust boundary in full stack frameworks like Next.js

In a Full Stack application, code runs in two completely different environments: on the Node.js Server and in the user's Web Browser.

Server-Side Variables

Accessible ONLY in backend Node.js runtime (API Routes, Server Actions, Server Components).

// Server-Side Only:
process.env.DATABASE_URL
process.env.STRIPE_SECRET_KEY
process.env.JWT_SECRET

// Never sent across the network
// Completely invisible to the browser!

Client-Side Variables (NEXT_PUBLIC_)

Inlined into the JavaScript bundle at build time and delivered directly to the browser.

// Client-Side Accessible:
process.env.NEXT_PUBLIC_API_URL
process.env.NEXT_PUBLIC_ANALYTICS_ID

// Inlined as string literal during build!
// Anyone can view via DevTools -> Sources
Cardinal Rule of Full Stack Web Security:
NEVER prefix a private credential with NEXT_PUBLIC_ (or Vite's VITE_). When a framework compiler sees that prefix, it literally replaces the variable expression with the raw string literal. Anyone who opens browser DevTools can inspect it in plain text.

🔥 04. Live Environment Variable Playground

Interactive full stack runtime simulator: Dev vs Prod

Simulate how a real full-stack web application reads configuration in Development vs Production. Modify values, toggle secret masking, and hit Apply Changes to inspect what the backend server receives versus what the browser bundle receives.

Active Environment:
Variable KeyTypeRuntime Value (development)Action
APP_NAME
Application display name
config
PORT
Local server listening port
config
API_URL
Backend service endpoint
config
DATABASE_URL
Local Postgres connection string
secret
API_KEY
Payment gateway test sandbox key
secret
NEXT_PUBLIC_ANALYTICS_ID
Browser client telemetry identifier
client

05. .env and .env.example Files

Local development workflows, templates, and native Node.js loading

.env (Local Machine Only — Ignored by Git)

# Local Developer Configuration
PORT=3000
APP_NAME="Pathubs Local"

# Local Real Secrets (DO NOT COMMIT!)
DATABASE_URL=postgresql://alex:mypass@localhost:5432/mydb
API_KEY=mock_stripe_test_51MzQ...
JWT_SECRET=super_secret_dev_key_123

.env.example (Committed to Git Repository)

# Required Application Configuration
PORT=3000
APP_NAME=

# Database Connection (PostgreSQL)
# Format: postgresql://[user]:[password]@[host]:[port]/[db]
DATABASE_URL=

# External API Keys (Get from dev portal)
API_KEY=
JWT_SECRET=
Modern Node.js Native Loading: --env-file (Node 20.6.0+)
Starting with Node.js v20.6.0+, you no longer need third-party packages like dotenv! Launch any script using native flags:
node --env-file=.env server.js or node --env-file-if-exists=.env server.js
Programmatic access is also built-in: process.loadEnvFile('.env').

06. Git + Secrets: The Fatal Mistake

Preventing credential leaks and executing the OWASP rotation protocol

.gitignore Configuration

# .gitignore
# Ignore all local environment files
.env
.env.local
.env.development.local
.env.test.local
.env.production.local

# DO NOT ignore the template!
!.env.example

Safe Team Onboarding Flow

# 1. Clone repository
git clone https://github.com/org/repo.git

# 2. Copy template to local file
cp .env.example .env

# 3. Fill in private local credentials
# 4. Git ignores .env automatically!
OWASP Protocol: What If a Real Secret is Leaked?
Do NOT simply delete the file or make a new commit!
Automated scraper bots monitor public commits in milliseconds. Deleting the file leaves the credential accessible in Git history.

MANDATORY REMEDIATION:
1. ROTATE / REVOKE IMMEDIATELY: Revoke the key immediately at the provider (AWS, Stripe, Database).
2. ISSUE A NEW SECRET: Generate a fresh key and inject it through secure container/cloud secret managers.
3. AUDIT ACCESS LOGS: Check whether unauthorized activity occurred during the exposure window.

07. Development vs Production

Same application code + different environment configuration = different runtime behavior

Development Environment

NODE_ENV="development"
PORT="3000"
LOG_LEVEL="debug"
API_URL="http://localhost:4000/api"
DATABASE_URL="postgresql://dev:dev@localhost:5432/app"
STRIPE_KEY="mock_sk_test_51...safe"
  • Fast local iteration with Hot Module Replacement
  • Verbose debug logging enabled
  • Safe sandbox credentials with zero financial impact

Production Environment

NODE_ENV="production"
PORT="8080"
LOG_LEVEL="warn"
API_URL="https://api.pathubs.com/v1"
DATABASE_URL="postgresql://prod:...@db-cluster.aws:5432/app?sslmode=require"
STRIPE_KEY="mock_sk_live_88...safe"
  • High performance optimizations with minified code
  • Strict TLS/SSL database connections
  • Live credentials with restricted IP allowlists

🔥 08. Real-World Debugging Lab

Diagnose and fix typical full-stack environment traps

Evaluate 4 realistic production incidents. Select the correct engineering decision for each scenario to reveal the technical rationale.

Incident #1

Scenario 1: Missing DATABASE_URL in Production

// server.js
const dbUrl = process.env.DATABASE_URL;
const pool = new Pool({ connectionString: dbUrl });
// Application starts listening on PORT 3000...

The application expects process.env.DATABASE_URL, but an engineer forgot to inject it into the production container. What should happen in a robust system?

Incident #2

Scenario 2: Secret Exposed via NEXT_PUBLIC_

// .env.production
NEXT_PUBLIC_STRIPE_SECRET_KEY=mock_sk_live_948194...safe

// src/components/CheckoutButton.tsx ('use client')
const stripeKey = process.env.NEXT_PUBLIC_STRIPE_SECRET_KEY;

A developer prefixed their private Stripe secret key with NEXT_PUBLIC_ so their React client component could access it. Is this key still a secret?

Incident #3

Scenario 3: .env with Live Database Password Committed to Git

commit 8f3b21c (HEAD -> main)
Author: Dev <dev@company.com>
Date:   3 days ago

Added feature and included .env with DB credentials

A developer committed a .env file containing live database passwords to a public GitHub repository 3 days ago. What is the correct, safe remediation workflow?

Incident #4

Scenario 4: Production App Fetching http://localhost:4000

// In production browser console:
GET http://localhost:4000/api/users net::ERR_CONNECTION_REFUSED

A Next.js frontend deployed to production is failing because it tries to request http://localhost:4000. Which configuration issue is the cause?

🎯 09. Final Mini Challenge: Variable Matrix

Classify variable types, trust boundaries, and Git policies

Given a realistic full-stack application configuration, decide the Category,Runtime Destination, and Git Policy for each variable.

Variable NameClassificationDestination BoundaryGit PolicyExplanation
APP_ENVComplete row to evaluate
DATABASE_URLComplete row to evaluate
API_URLComplete row to evaluate
API_KEYComplete row to evaluate
PORTComplete row to evaluate
Full Stack Mental Model: The Unbroken Lifecycle
SOURCE CODE ➔ reads configuration ➔ ENVIRONMENT ➔ variables provided at runtime ➔ APPLICATION

.env is Local Convenience

.env is a local developer tool, NOT a security perimeter. Never commit it to Git.

Client Variables Are Public

Any variable prefixed with NEXT_PUBLIC_ is readable by anyone who opens DevTools.