HomeBlog

Centralizing Your FastAPI Configuration Settings with Pydantic Settings and .env Files

5 min read
Centralized FastAPI settings management using Pydantic Settings and .env file for secure, organized configuration

Managing settings for a FastAPI project can get messy if you spread configuration across multiple files or hard-code secrets. The best way is to keep all your settings in one place and load them from a .env file. Pydantic Settings provides optional Pydantic features for loading a settings or config class from environment variables or secrets files. Pydantic v2 and pydantic-settings make this easy and reliable.

Why Centralize Settings?

Centralizing settings means you have a single source of truth for your app’s configuration. You avoid mistakes, make your code easier to maintain, and keep secrets out of your source code.

Installing pydantic-settings

To use pydantic-settings with Pydantic v2, you need to install it first. Run this command in your project directory:

pip install pydantic-settings

Make sure you have Pydantic v2 installed as well:

pip install pydantic

Example: Settings with Pydantic v2

Here’s a simple settings module using Pydantic v2 and pydantic-settings. This reads values from a .env file and makes them available throughout your app.

from enum import Enum
from functools import lru_cache
from pydantic import Field
from pydantic_settings import BaseSettings

class EnvironmentEnum(str, Enum):
    TEST = "TEST"
    PRODUCTION = "PRODUCTION"

class Settings(BaseSettings):
    # Environment settings
    DEBUG: bool = Field(default=False, validation_alias="DEBUG", alias_priority=2)
    RELOAD: bool = Field(default=False, validation_alias="RELOAD", alias_priority=2)
    ENVIRONMENT: str = Field(default=EnvironmentEnum.TEST, validation_alias="ENVIRONMENT", alias_priority=2)

    # POSTGRES DATABASE
    POSTGRES_USER: str = Field(default="", validation_alias="POSTGRES_USER", alias_priority=2)
    POSTGRES_PASSWORD: str = Field(default="", validation_alias="POSTGRES_PASSWORD", alias_priority=2)
    POSTGRES_HOST: str = Field(default="", validation_alias="POSTGRES_HOST", alias_priority=2)
    POSTGRES_PORT: str = Field(default="", validation_alias="POSTGRES_PORT", alias_priority=2)
    POSTGRES_DATABASE_NAME: str = Field(default="", validation_alias="POSTGRES_DATABASE_NAME", alias_priority=2)

    SECRET_KEY: str = Field(default="", validation_alias="SECRET_KEY", alias_priority=2)

    class Config:
        env_file = ".env"
        env_file_encoding = "utf-8"
        extra = "ignore"

@lru_cache
def get_settings():
    return Settings()

What Are validation_alias and alias_priority?

When you use Pydantic’s Field, you can set a validation_alias. This tells Pydantic to look for a specific name in your environment variables or input data, even if your Python attribute has a different name. It’s useful if your config keys don’t match your Python variable names.

alias_priority comes into play when you have multiple possible aliases for a field. The priority number decides which alias Pydantic should prefer if more than one is present. A lower number means higher priority.

In short, validation_alias lets you map your Python settings to environment variable names, and alias_priority helps Pydantic choose the right one if there are several options.

What Do DEBUG and RELOAD Do?

  • DEBUG: When set to True, FastAPI will show detailed error messages and enable debug features. This is useful during development but should be False in production.
  • RELOAD: If True, FastAPI will automatically reload the server when you change your code. This is handy for development but not for production.

Why Use lru_cache?

The @lru_cache decorator makes sure your settings are only loaded once. This is important because you don’t want to read and parse your .env file every time you need a setting. It saves memory and speeds up your app.

How to Use Settings in Other Modules

You can access your settings anywhere in your app by importing and calling get_settings(). Here’s an example:

from app.config.main import get_settings

settings = get_settings()
print(settings.POSTGRES_USER)

This gives you access to all your configuration values, and you know they’re coming from your centralized settings.

Want to see a real-world example of using these settings in action? Check out my blog post on connecting FastAPI to a serverless database with pool_pre_ping in SQLAlchemy.

Example .env File

Here’s what your .env file might look like:

DEBUG=True
RELOAD=True
ENVIRONMENT=TEST

POSTGRES_USER=your_user
POSTGRES_PASSWORD=your_password
POSTGRES_HOST=localhost
POSTGRES_PORT=5432
POSTGRES_DATABASE_NAME=your_database

SECRET_KEY=your_secret_key

Note: For production environments, you should not store sensitive credentials like database passwords in your .env file or commit them to version control/GitHub. Instead, use a secure service such as Google Secret Manager to manage secrets safely. You can read more about using Google Secret Manager in my blog post on running database migrations with Alembic in Google Cloud Build.

Final Thoughts

Centralizing your settings with Pydantic and a .env file is a simple way to keep your FastAPI project organized. It’s not complicated, and it saves you headaches down the road. Use lru_cache to avoid repeated reads, and keep your secrets out of your codebase. If you’re still hard-coding settings, it’s time to switch.

About the Author

David Muraya is a Solutions Architect specializing in Python, FastAPI, and Cloud Infrastructure. He is passionate about building scalable, production-ready applications and sharing his knowledge with the developer community. You can connect with him on LinkedIn.

Related Blog Posts

Enjoyed this blog post? Check out these related posts!

Advanced Performance Tuning for FastAPI on Google Cloud Run

Advanced Performance Tuning for FastAPI on Google Cloud Run

From Cold Starts to Concurrency: A Deep Dive into FastAPI Performance on Cloud Run.

Read More..

Optimizing Reflex Performance on Google Cloud Run

Optimizing Reflex Performance on Google Cloud Run

A Comparison of Gunicorn, Uvicorn, and Granian for Running Reflex Apps

Read More..

Full-Text Search: Using the Trigram Tokenizer Algorithm to Match Peoples Names

Full-Text Search: Using the Trigram Tokenizer Algorithm to Match Peoples Names

Leveraging Full Text Search and Trigram Tokenization for Efficient Name Matching

Read More..

Running Database Migrations with Alembic in Google Cloud Build

Running Database Migrations with Alembic in Google Cloud Build

How to Organize and Load FastAPI Settings from a .env File Using Pydantic v2

Read More..

Contact Me

Have a project in mind? Send me an email at hello@davidmuraya.com and let's bring your ideas to life. I am always available for exciting discussions.

© 2025 David Muraya. All rights reserved.