Skip to content

The 12-Factor App Configuration Factor

The Twelve-Factor App is a set of best practices for building modern, scalable, and maintainable software-as-a-service applications. It provides a battle-tested guide for creating robust applications that are easy to deploy and manage.

This document focuses on the third and one of the most critical factors: Configuration.

An app’s config is everything that is likely to vary between deploys (development, staging, production). This includes database credentials, API keys for external services, or environment-specific feature flags. — https://12factor.net/config

A core rule of the 12-Factor methodology is the strict separation of code and config. Your codebase should remain the same across all deployment environments, while the configuration changes.

A simple test for this is to ask: “Could you make your codebase open-source at any moment without compromising any credentials?” If the answer is no, you have configuration mixed in with your code.

While the 12-Factor methodology advocates for storing all configuration in environment variables, a common and powerful pattern is to use a hybrid approach. This combines the clarity of configuration files with the flexibility of environment variables.

1. Configuration Files for Defaults and Structure

Section titled “1. Configuration Files for Defaults and Structure”

Start with base configuration files that are isolated from your application code. These files are excellent for:

  • Defining default values for your application.
  • Establishing the schema or “shape” of your configuration based on the target environment.
  • Storing non-sensitive, environment-agnostic settings.

These files can be checked into version control, but they must not contain any secrets like passwords or API keys. They serve as the foundational, default layer of your configuration.

2. Environment Variable Overrides for Flexibility and Security

Section titled “2. Environment Variable Overrides for Flexibility and Security”

For any setting that changes between environments or is sensitive, you should use environment variables to override the values defined in your configuration files.

This approach is superior to hardcoding conditional logic (e.g., if environment is 'production' then use this value) directly in your application. By using overrides, your code remains clean and unaware of the specific environment it’s running in.

Environment variables are the ideal way to inject deployment-specific settings because they are:

  • Secure: Secrets are never stored in your codebase. They are supplied by the deployment environment (e.g., a Docker container, a CI/CD pipeline, or a PaaS).
  • Flexible: You can easily change a database URL or an API key for a production deployment without touching a single line of code or a config file.
  • Standardized: They are a language- and OS-agnostic standard, making your application highly portable.
  • Separate Code and Config: Never hardcode configuration values like credentials or hostnames in your code.
  • Use Files for a Base: Use configuration files to define the shape and default values of your application’s settings.
  • Use Environment Variables to Override: For secrets and environment-specific values, use environment variables as the ultimate source of truth. This is cleaner and more robust than conditional logic in your code.
  • Never Commit Secrets: Your application’s repository should always be safe to make public.