# How to Organize Configuration Files in Go Projects: The /configs Directory Standard

> Organize Go project configuration files in a /configs directory. Separate operational assets from source code and enable environment-specific customization for better project management.

- Repository: [golang-standards/project-layout](https://github.com/golang-standards/project-layout)
- Tags: best-practices
- Published: 2026-03-06

---

**Place all configuration templates and default files in a dedicated `/configs` directory at the repository root to keep operational assets separate from source code and enable environment-specific customization.**

The golang-standards/project-layout repository establishes a widely adopted convention for structuring Go applications. Organizing configuration files in Go projects requires a predictable location that tooling can discover without cluttering your `cmd/` or `pkg/` directories. This standard places all configuration-related assets in a top-level `/configs` folder, separating deployment concerns from implementation logic.

## The /configs Directory Structure and Purpose

According to the project-layout standard, the `/configs` directory at the repository root holds **configuration file templates or default configs**. The repository's [`README.md`](https://github.com/golang-standards/project-layout/blob/main/README.md) explicitly states this folder is designed for files that can be copied or rendered for different environments.

The [`configs/README.md`](https://github.com/golang-standards/project-layout/blob/main/configs/README.md) file provides specific guidance: "Put your `confd` or `consul-template` template files here." This location serves as the single source of truth for all configuration artifacts, distinct from the application source code and aligned with other operational folders like `/init`, `/scripts`, and `/build`.

## Benefits of Separating Configuration from Source Code

Maintaining a dedicated `/configs` directory delivers three primary advantages:

- **Versioning and Auditing**: Keeping configuration separate from source code makes it easier to track changes to operational settings independently of feature development.
- **Environment Customization**: Default configs stored in `/configs` can be copied and modified for development, staging, and production without modifying the codebase.
- **Tooling Integration**: Libraries like **Viper** and **envconfig** can load files from a predictable location without cluttering the `cmd/` or `pkg/` hierarchy.

## Typical Organization Inside /configs

While the standard does not mandate specific subdirectories, the following structure represents best practices for organizing configuration files:

- **`json/`** – Contains JSON default configs such as [`config.dev.json`](https://github.com/golang-standards/project-layout/blob/main/config.dev.json) and [`config.prod.json`](https://github.com/golang-standards/project-layout/blob/main/config.prod.json).
- **`yaml/`** – Stores YAML equivalents like [`config.yaml`](https://github.com/golang-standards/project-layout/blob/main/config.yaml) for environment-specific settings.
- **`templates/`** – Holds text/template files used by tools like `confd` for dynamic configuration generation.
- **`example/`** – Provides sample config files for new developers to copy and customize.
- **`scripts/`** – Includes helper scripts such as [`render.sh`](https://github.com/golang-standards/project-layout/blob/main/render.sh) that process template files.

### JSON and YAML Defaults

Place environment-specific defaults in `configs/json/` or `configs/yaml/` subdirectories. This allows applications to load [`config.dev.json`](https://github.com/golang-standards/project-layout/blob/main/config.dev.json) for local development while operations teams mount [`config.prod.json`](https://github.com/golang-standards/project-layout/blob/main/config.prod.json) in production containers.

### Template Files for Dynamic Configuration

Store `confd` or `consul-template` template files in `configs/templates/`. These files support dynamic configuration generation based on environment variables or service discovery, which is essential for containerized deployments orchestrated by Kubernetes or Docker Swarm.

## Loading Configuration Files in Go

Once files are organized in `/configs`, your application needs reliable methods to load them. The following examples demonstrate standard patterns using popular configuration libraries.

### Using Viper to Load from /configs

**Viper** supports multiple config formats and can be pointed directly at the `/configs` directory. Create a reusable loader in [`pkg/config/config.go`](https://github.com/golang-standards/project-layout/blob/main/pkg/config/config.go):

```go
package config

import (
	"log"
	"strings"

	"github.com/spf13/viper"
)

// Load reads a config file from the project's /configs directory.
// env may be "dev", "staging", "prod", etc.
func Load(env string) {
	// Directory relative to the project root.
	viper.AddConfigPath("configs")
	// Look for both JSON and YAML files.
	for _, ext := range []string{"json", "yaml", "yml"} {
		viper.SetConfigName("config." + env)
		viper.SetConfigType(ext)
		if err := viper.ReadInConfig(); err == nil {
			break
		}
	}

	if err := viper.ReadInConfig(); err != nil {
		log.Fatalf("cannot read config for %s: %v", env, err)
	}

	// Example: bind environment variables (override file values)
	viper.AutomaticEnv()
	viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
}

```

This implementation follows the project-layout convention by placing reusable configuration logic in `pkg/config/`, while the actual config files remain in `/configs` at the repository root.

### Using envconfig with Example Files

For projects preferring environment variables over files, place a `.env.example` file in `configs/` to document required variables. Implement the loader in [`internal/config/app_config.go`](https://github.com/golang-standards/project-layout/blob/main/internal/config/app_config.go):

```go
package config

import (
	"log"

	"github.com/kelseyhightower/envconfig"
)

// Settings defines the configuration schema.
type Settings struct {
	Port        int    `envconfig:"APP_PORT" default:"8080"`
	DatabaseURL string `envconfig:"DATABASE_URL" required:"true"`
}

// LoadEnv reads variables, falling back to a .env file placed in /configs.
func LoadEnv() Settings {
	var s Settings
	if err := envconfig.Process("", &s); err != nil {
		log.Fatalf("failed to parse env: %v", err)
	}
	return s
}

```

## Key Files in the Configuration Layout

Understanding the standard requires familiarity with these specific files:

- **`README.md#configs`** – The main repository documentation describing the `/configs` purpose within the overall layout.
- **[`configs/README.md`](https://github.com/golang-standards/project-layout/blob/main/configs/README.md)** – Specific guidance on what belongs in the folder, explicitly mentioning support for `confd` and `consul-template` files.
- **`pkg/config/`** – The conventional location for reusable configuration loading libraries that import settings from `/configs`.
- **`internal/config/`** – Private configuration helpers that implement business-specific parsing logic while keeping the `/configs` directory focused on data files.

## Summary

- Place all configuration templates and default files in the **`/configs`** directory at the repository root.
- Separate JSON, YAML, and template files into logical subdirectories like `json/`, `yaml/`, and `templates/`.
- Keep configuration loading logic in **`pkg/config/`** or **`internal/config/`** while data files remain in `/configs`.
- Use **Viper** for file-based configuration loading from the predictable `/configs` path.
- Document environment variables in **`configs/.env.example`** when using **envconfig** or similar tools.

## Frequently Asked Questions

### Where should I put environment-specific configuration files in a Go project?

Place environment-specific files like [`config.dev.json`](https://github.com/golang-standards/project-layout/blob/main/config.dev.json) or [`config.prod.yaml`](https://github.com/golang-standards/project-layout/blob/main/config.prod.yaml) in the `/configs` directory at your repository root. According to the golang-standards/project-layout, this directory holds all configuration file templates or default configs, keeping them separate from your source code in `cmd/` and `pkg/`.

### Can I store sensitive configuration values in the /configs directory?

No. The `/configs` directory is intended for templates and default configurations only. Store sensitive values in environment variables or secure vaults. You can place a `.env.example` file in `/configs` to document required variables without exposing secrets.

### What is the difference between /configs and /config in the Go project layout?

The standard specifies **`/configs`** (plural) at the repository root for configuration file templates. While some projects use `/config` (singular) for application-specific configuration code, the golang-standards/project-layout reserves `/configs` for operational assets and templates like `confd` or `consul-template` files.

### How do I load configuration files from /configs in my Go application?

Use configuration libraries like **Viper** that support custom config paths. Point Viper to the `configs` directory relative to your project root with `viper.AddConfigPath("configs")`. For environment-variable based configuration, place example files in `/configs` and load them using **envconfig** or similar tools.