# How to Manage Environment-Specific Configurations in FastAPI: Local, Staging, and Production

> Master environment-specific FastAPI configurations for local staging and production. Learn to centralize settings with Pydantic, load from env vars or .env files, and control features using the environment flag.

- Repository: [Benav Labs/fastapi-boilerplate](https://github.com/benavlabs/fastapi-boilerplate)
- Tags: how-to-guide
- Published: 2026-02-26

---

**Manage environment-specific configurations in FastAPI by using a centralized Pydantic Settings class with an EnvironmentOption enum, loading values from environment variables or .env files, and gating features like API docs and HTTPS enforcement based on the ENVIRONMENT flag.**

The `benavlabs/fastapi-boilerplate` repository demonstrates a robust pattern for managing environment-specific configurations through a single source of truth. By centralizing all settings in Pydantic models and using an enumeration to distinguish between local, staging, and production deployments, the codebase achieves deterministic, environment-aware behavior without scattering conditional logic throughout the application.

## Core Configuration Architecture

The configuration system lives in [`src/app/core/config.py`](https://github.com/benavlabs/fastapi-boilerplate/blob/main/src/app/core/config.py) and relies on Pydantic's `BaseSettings` to handle environment variable parsing and validation.

### Environment Enumeration

The `EnvironmentOption` enum defines the three supported deployment targets:

```python
class EnvironmentOption(str, Enum):
    LOCAL = "local"
    STAGING = "staging"
    PRODUCTION = "production"

```

This enum is used to type-check the `ENVIRONMENT` variable across the entire application, ensuring only valid values are accepted.

### Settings Composition

The `EnvironmentSettings` class holds the current environment flag, defaulting to local development:

```python
class EnvironmentSettings(BaseSettings):
    ENVIRONMENT: EnvironmentOption = EnvironmentOption.LOCAL

```

The main `Settings` class combines multiple `BaseSettings` subclasses (such as `PostgresSettings` and `RedisCacheSettings`) into a single global singleton. It automatically loads values from a `.env` file located at the project root:

```python
class Settings(EnvironmentSettings, PostgresSettings, ...):
    model_config = SettingsConfigDict(
        env_file=os.path.join(os.path.dirname(os.path.realpath(__file__)), "..", "..", ".env")
    )

settings = Settings()

```

## Switching Between Environments

To manage environment-specific configurations, you manipulate the `ENVIRONMENT` variable and associated settings in your `.env` file or hosting platform.

### Basic Environment Selection

Set the `ENVIRONMENT` variable to switch contexts:

```dotenv

# .env (staging example)

ENVIRONMENT=staging
APP_NAME="My FastAPI App – Staging"
POSTGRES_SERVER=staging-db.example.com
REDIS_CACHE_HOST=staging-redis.example.com

```

When the application starts, `settings.ENVIRONMENT` reflects this value. You can access it anywhere in the code to adjust behavior:

```python

# src/app/api/v1/health.py

response = {
    "environment": settings.ENVIRONMENT.value,
    # ...

}

```

### Optional Per-Environment Files

While the boilerplate defaults to a single `.env` file, you can maintain separate files (`.env.local`, `.env.staging`, `.env.prod`) and deploy the appropriate file as `.env` during your CI/CD pipeline. Alternatively, inject variables directly via your hosting platform's secret management system, as Pydantic Settings prioritizes OS environment variables over file values.

## Environment-Specific Behavior

The codebase uses the `ENVIRONMENT` flag to conditionally enable or disable features based on the deployment context.

### API Documentation Visibility

In [`src/app/core/setup.py`](https://github.com/benavlabs/fastapi-boilerplate/blob/main/src/app/core/setup.py), the `create_application` function disables interactive documentation in production:

```python
if settings.ENVIRONMENT != EnvironmentOption.PRODUCTION:
    # Enable /docs and /redoc

    docs_url = "/docs"
    redoc_url = "/redoc"
else:
    docs_url = None
    redoc_url = None

```

For staging environments, documentation remains accessible but requires super-user authentication via `Depends(get_current_superuser)`, protecting internal endpoints from public access while allowing developer debugging.

### Admin Interface Security

The admin UI enforces HTTPS exclusively in production. In [`src/app/admin/initialize.py`](https://github.com/benavlabs/fastapi-boilerplate/blob/main/src/app/admin/initialize.py), the setup logic reads:

```python
enforce_https=settings.ENVIRONMENT == EnvironmentOption.PRODUCTION

```

This ensures local developers can test the admin panel without TLS certificates while production deployments maintain strict transport security.

### Startup Lifecycle Adjustments

The `lifespan_factory` in [`src/app/core/setup.py`](https://github.com/benavlabs/fastapi-boilerplate/blob/main/src/app/core/setup.py) receives concrete settings subclasses to attach the correct event handlers for database connections, Redis pools, and rate-limiting backends based on the current environment's resource configuration.

## Practical Configuration Examples

### Local Development

Create a `.env` file in the project root with local credentials:

```dotenv
ENVIRONMENT=local
APP_NAME="FastAPI Boilerplate – Local"
POSTGRES_SERVER=localhost
POSTGRES_PORT=5432
POSTGRES_USER=postgres
POSTGRES_PASSWORD=postgres
POSTGRES_DB=postgres
REDIS_CACHE_HOST=localhost
REDIS_QUEUE_HOST=localhost
REDIS_RATE_LIMIT_HOST=localhost

```

Run with `uvicorn src.app.main:app --reload`. API documentation is publicly available at `/docs`, and HTTPS enforcement is disabled.

### Staging Deployment

```dotenv
ENVIRONMENT=staging
APP_NAME="FastAPI Boilerplate – Staging"
POSTGRES_SERVER=staging-db.example.com
POSTGRES_USER=staging_user
POSTGRES_PASSWORD=staging_pass
POSTGRES_DB=staging_db
REDIS_CACHE_HOST=staging-redis.example.com
REDIS_QUEUE_HOST=staging-redis-queue.example.com
REDIS_RATE_LIMIT_HOST=staging-redis-rate.example.com

```

In this mode:
- Documentation requires super-user authentication
- Admin UI allows HTTP connections
- All data services point to staging infrastructure

### Production Deployment

```dotenv
ENVIRONMENT=production
APP_NAME="FastAPI Boilerplate"
POSTGRES_SERVER=prod-db.example.com
POSTGRES_USER=prod_user
POSTGRES_PASSWORD=prod_secure_pass
POSTGRES_DB=prod_db
REDIS_CACHE_HOST=prod-redis.example.com
REDIS_QUEUE_HOST=prod-redis-queue.example.com
REDIS_RATE_LIMIT_HOST=prod-redis-rate.example.com

```

Production specifics include:
- **Interactive API documentation is completely disabled** (`docs_url=None`, `redoc_url=None`)
- Admin UI forces HTTPS connections
- Health endpoints report `production` status for monitoring systems

## Extending the Configuration

To add new environment-specific variables, define them in a `BaseSettings` subclass or directly in `AppSettings`:

```python
class AppSettings(BaseSettings):
    APP_NAME: str = "FastAPI app"
    SENTRY_DSN: str | None = None
    FEATURE_FLAG_V2: bool = False

```

These fields automatically become available via `settings.SENTRY_DSN` and can be set per-environment in your `.env` files:

```dotenv

# .env.production

SENTRY_DSN=https://...
FEATURE_FLAG_V2=true

```

## Summary

- **Centralize configuration** in [`src/app/core/config.py`](https://github.com/benavlabs/fastapi-boilerplate/blob/main/src/app/core/config.py) using Pydantic's `BaseSettings` to manage environment-specific configurations with type safety.
- **Use the `EnvironmentOption` enum** to represent local, staging, and production states, preventing invalid environment strings.
- **Control feature visibility** by checking `settings.ENVIRONMENT` in [`src/app/core/setup.py`](https://github.com/benavlabs/fastapi-boilerplate/blob/main/src/app/core/setup.py) to disable docs in production and protect them in staging.
- **Enforce security policies** such as HTTPS-only admin access based on the environment flag in [`src/app/admin/initialize.py`](https://github.com/benavlabs/fastapi-boilerplate/blob/main/src/app/admin/initialize.py).
- **Maintain separate .env files** for each deployment target or inject variables via your platform's secret management to switch contexts without code changes.

## Frequently Asked Questions

### How does the FastAPI boilerplate determine which environment it is running in?

The application reads the `ENVIRONMENT` variable from the operating system environment or the `.env` file, validates it against the `EnvironmentOption` enum in [`src/app/core/config.py`](https://github.com/benavlabs/fastapi-boilerplate/blob/main/src/app/core/config.py), and stores it in the global `settings` object. This value is then referenced throughout the codebase to adjust behavior.

### Can I use multiple .env files for different environments?

While the boilerplate defaults to loading a single `.env` file from the project root, you can maintain separate files (e.g., `.env.staging`, `.env.prod`) and copy or symlink the appropriate file to `.env` during deployment. Alternatively, set variables directly in your hosting platform's environment, as Pydantic Settings prioritizes OS environment variables over file-based values.

### Why is the API documentation disabled in production?

According to the source code in [`src/app/core/setup.py`](https://github.com/benavlabs/fastapi-boilerplate/blob/main/src/app/core/setup.py), interactive documentation endpoints (`/docs` and `/redoc`) are disabled in production to reduce the attack surface and prevent exposing internal API schemas to the public internet. In staging environments, documentation remains available but requires super-user authentication.

### How do I add a new configuration variable that changes per environment?

Define the variable in a `BaseSettings` subclass within [`src/app/core/config.py`](https://github.com/benavlabs/fastapi-boilerplate/blob/main/src/app/core/config.py) (such as `AppSettings`), specifying a type and default value. The variable will automatically be available via the global `settings` object and can be overridden per environment by setting it in the appropriate `.env` file or deployment platform.