APIs: Concepts, Design, Requests, Responses, and Integration
Environment Variables: Configure APIs Safely Across Environments
Learn what environment variables are, how APIs read them, and how to manage configuration, secrets, local development, deployment, and validation safely.
Environment variables let an API receive configuration from the system that starts it. They are useful for changing ports, database connections, service URLs, feature flags, and credentials without editing application source code.
What Is an Environment Variable?
An environment variable is a named value provided by the operating system or execution platform to a process. A process environment is the collection of environment variables available to a running program.
For example, a process might receive these values:
PORT=3000
APP_ENV=development
DATABASE_URL=postgresql://user:password@localhost:5432/appdb
The application reads these values when it starts or while it runs. The exact access syntax depends on the programming language and framework, but the underlying idea is the same: the execution environment supplies named values to the program.
Configuration versus application variables
Configuration means settings that control how an application runs without changing its source code. Environment variables are commonly used for configuration because the same codebase can run with different settings.
- Hard-coded constant: a value written directly into source code, such as
const port = 3000. Changing it requires editing and rebuilding or redeploying the code. - Ordinary application variable: a value created and managed inside the program while it runs. It may hold user input, a calculated result, or a setting loaded from somewhere else.
- Environment variable: a named value supplied from outside the program, usually by the operating system, a shell, a container, a hosting platform, or a deployment system.
This separation keeps operational choices outside the source code. It also makes it possible to promote the same application build through development, test, staging, and production with different settings.
Common API Configuration Uses
| Variable name | Purpose | Example format | Required | Sensitive |
|---|---|---|---|---|
API_BASE_URL | Address of an API or service | https://api.example.com | Often | No |
PORT | Port on which the server listens | 3000 | Often no | No |
APP_ENV | Runtime mode | development | Recommended | No |
DATABASE_URL | Database connection details | postgresql://user:password@host:5432/db | Usually | Usually |
API_KEY | Credential for an external API | replace-with-local-secret | Depends | Yes |
FEATURE_REPORTS | Enables or disables a feature | true | No | No |
Endpoints and base URLs
An API may call a payment, weather, search, or identity service. Store the service's base URL in a variable such as WEATHER_API_BASE_URL rather than embedding a fixed endpoint in source code. Development can point to a mock service while production points to the live service.
Ports and runtime modes
A hosting platform may assign a port dynamically. A variable such as PORT lets the server listen on the required port. A variable such as APP_ENV can select development, test, staging, or production behavior.
Databases and credentials
DATABASE_URL can contain a host, port, database name, and authentication details. Other common values include database usernames, passwords, TLS settings, and connection pool limits. Treat connection strings containing credentials as secrets.
API keys, tokens, and feature flags
An API key is a credential used to identify or authorize an application when it calls an API. Access tokens, private keys, signing secrets, and webhook secrets are also sensitive configuration. Feature flags can be represented as strings such as true, false, or a controlled variant name; applications should parse and validate them rather than assuming every nonempty value means true.
Reading Variables in an Application
A program asks its runtime or framework for a variable by name. For example, language runtimes often expose an environment collection, while frameworks may provide a configuration service that reads from that collection. The exact syntax is language-specific, so consult the documentation for the runtime you use.
# Conceptual application logic
port = read_environment("PORT")
mode = read_environment("APP_ENV")
if port is missing:
port = 3000
start_server(port=convert_to_integer(port), mode=mode)
Values normally arrive as text. Convert them before use: parse ports as integers, interpret boolean flags explicitly, and validate URLs and connection strings. Do not assume that a missing value, an empty value, and a malformed value are equivalent.
Missing values, defaults, and startup validation
- Use a safe default for a non-sensitive setting when a default is genuinely appropriate, such as a local development port.
- Require values that are essential to operation, such as a production database URL or signing secret.
- Validate format during startup, before the application begins accepting requests.
- Fail with a clear message naming the missing or invalid variable, but never print its secret value.
Configuration validation is the practice of checking that required configuration exists and has an acceptable format before the application runs. An invalid configuration should cause a deliberate startup failure rather than a confusing error later during a request.
required = ["DATABASE_URL", "API_SECRET"]
for name in required:
value = read_environment(name)
if value is missing or value is empty:
stop_startup("Missing required configuration: " + name)
if not is_valid_url(read_environment("DATABASE_URL")):
stop_startup("DATABASE_URL has an invalid format")
Separating Development, Test, Staging, and Production
A runtime environment is the context in which software executes. Development is usually a local environment, test is used for automated or controlled verification, staging resembles production for final checks, and production serves real users or business workloads.
| Setting | Development | Test or staging | Production |
|---|---|---|---|
API_BASE_URL | Local mock or sandbox | Test or staging service | Live service |
DATABASE_URL | Local database | Isolated test database | Managed production database |
APP_ENV | development | test or staging | production |
| Logging | Detailed but sanitized | Diagnostic and sanitized | Controlled and sanitized |
| Credentials | Local or sandbox credentials | Dedicated non-production credentials | Production-only credentials |
Each environment can supply different values while the application code remains unchanged. Never reuse production credentials for local development. Local tools, logs, screenshots, and accidental commits create unnecessary exposure risk.
Security and Secret Handling
A secret is sensitive configuration such as a password, token, private key, signing key, webhook secret, or API key. Keep secrets in environment variables or, preferably for many production systems, a dedicated secret manager that controls access, auditing, rotation, and encryption.
- Do not commit real secrets to source control, including inside source files, sample files, documentation, or local environment files.
- Do not expose server-side secrets in browser code, mobile application bundles, public API responses, or other client-side artifacts. Anything shipped to a client should be considered visible.
- Mask secrets in logs, exception messages, screenshots, terminal recordings, CI/CD output, and support tickets.
- Use separate credentials for development, test, staging, and production.
- Rotate or revoke a credential immediately if it may have been exposed.
Environment variables improve the separation of configuration from source code, but they are not a complete secret-management solution. A process, administrator, debugging tool, crash report, or misconfigured platform may still expose them. Limit access and choose a secret manager when the deployment requires stronger controls.
For related API credential concepts, see Credentials and Config.
Local Development Workflow
One command versus a shell session
On macOS and Linux, an assignment before a command applies to that command invocation only:
PORT=3000 npm start
Exporting a variable makes it available to commands started from the current shell session:
export PORT=3000
npm start
On Windows Command Prompt, use:
set PORT=3000
On Windows PowerShell, use:
$env:PORT = "3000"
Session-based values usually disappear when the terminal session ends. A variable set in one terminal is not automatically available in another terminal, editor task, container, or service process.
Local dotenv files
A dotenv file is a local file convention, commonly named .env, containing environment-style key-value entries. A framework or dotenv loader may read it when the application starts. Support and precedence rules differ, so verify how your framework loads files and which values take priority.
PORT=3000
APP_ENV=development
DATABASE_URL=
API_SECRET=
Keep the real .env file outside source control. Commit a template such as .env.example with variable names, safe examples, and empty placeholders:
PORT=3000
APP_ENV=development
DATABASE_URL=
WEATHER_API_KEY=
A template helps teammates understand the required setup without sharing credentials. An ignore rule can exclude local files while retaining the template:
.env
.env.*
!.env.example
Deployment and Automation
Production configuration is commonly supplied by a hosting platform, container runtime, CI/CD system, or operating-system service definition. Configure variables at deployment or process-start time instead of embedding secrets and environment-specific values in a build artifact.
- Hosting platforms: define variables in the service's application settings or secret configuration.
- Containers: pass non-secret configuration and secrets through the container runtime or an orchestrator's secret facility.
- CI/CD systems: store protected variables or secrets and expose them only to jobs that need them.
- Operating-system services: configure the service account or service definition that launches the API.
Changing a variable often affects only newly started processes. The application may require a restart, a new container, or a redeployment before the change takes effect. Confirm the platform's behavior and avoid printing the complete environment while diagnosing a deployment.
Configuration settings can also be managed through an application configuration design; see Config and Settings for related API topics.
Configuration Design Practices
- Use clear, consistent uppercase names with underscores, such as
API_BASE_URL,DATABASE_URL, andLOG_LEVEL. - Document each variable's purpose, expected format, whether it is required, and a safe example value.
- Parse values according to their type instead of treating every string as valid.
- Validate required variables and fail clearly during startup.
- Avoid silently using unsafe defaults for credentials, signing keys, database connections, or production modes.
- Keep naming and behavior consistent across environments so deployment differences are intentional and easy to review.
- Log variable names or safe status indicators when diagnosing configuration, never secret values.
Choosing Where to Store Configuration
| Method | Best use | Security considerations | Source-control guidance |
|---|---|---|---|
| Shell variables | Quick local commands and temporary testing | May be visible in shell history or process tools | Do not record real secrets in scripts or history |
| Local dotenv file | Convenient local development | Protect file permissions and exclude real values from commits | Ignore .env; commit only a safe template |
| Deployment platform variables | Application configuration at release time | Use access controls, masking, and audit features | Store references or configuration metadata, not secret values |
| Dedicated secret manager | Production secrets and controlled access | Supports policies, rotation, auditing, and encryption | Commit only the lookup configuration, never retrieved secrets |
| Configuration file | Large structured non-secret settings | Restrict access if it contains sensitive values | Commit safe defaults; inject secrets separately |
Troubleshooting Environment Variables
“A required variable is missing”
- Check the documented variable name, including spelling and letter case.
- Confirm that the variable was set in the shell, process, service, or deployment where the API actually runs.
- Check whether the application loads its local environment file and whether the file is in the expected directory.
- Restart the process after changing configuration.
- Inspect only non-sensitive values or safe presence indicators.
Local works but production fails
- Verify that all required variables were configured in the production platform.
- Check URL, port, and connection-string formats without revealing credentials.
- Look for a development-only default that production is accidentally using.
- Use startup validation and log only safe diagnostic details.
A secret was committed
- Revoke or rotate the exposed credential immediately.
- Remove it from active configuration and repository history according to the project's policy.
- Add ignore rules and a safe example file so the mistake is less likely to recur.
- Review access logs and affected integrations when appropriate.
Deleting a secret from the latest file is not enough if it remains in repository history, build logs, caches, or screenshots. Treat the value as compromised until it has been rotated.
Spaces or special characters are interpreted incorrectly
Shells and dotenv parsers have their own quoting rules. Quote values when the syntax supports it, and use the correctly encoded form for structured values such as database URLs. A password containing reserved URL characters may need URL encoding before it is placed in a connection string.
Exam-Relevant Summary
- An environment variable is a named value supplied by the operating system or execution platform to a process.
- Environment variables separate configuration from application source code and allow one codebase to run in multiple environments.
- Ports, base URLs, database settings, feature flags, API keys, tokens, and other credentials are common API configuration values.
- Environment values are usually strings, so applications should parse, validate, and safely default them.
- Required configuration should be checked during startup, with clear errors that do not reveal secret values.
- Production credentials must not be reused in local development or exposed in client-side code.
- Local dotenv files are convenient, but real secret files should be ignored by source control.
- Environment variables reduce accidental source-code exposure but do not replace a dedicated secret-management system.
- Deployment configuration changes may require a restart or redeployment.