Skip to main content
Kratos provides a flexible configuration management system that supports multiple sources, hot-reloading, and type-safe value access.

Core Interface

config/config.go:28-34
type Config interface {
    Load() error
    Scan(v any) error
    Value(key string) Value
    Watch(key string, o Observer) error
    Close() error
}
Load
func() error
Load configuration from all sources
Scan
func(v any) error
Unmarshal entire configuration into a struct
Value
func(key string) Value
Get a specific configuration value by key
Watch
func(key string, o Observer) error
Watch for changes to a specific key
Close
func() error
Close all configuration sources and stop watching

Creating a Config

config/config.go:45-60
import (
    "github.com/go-kratos/kratos/v2/config"
    "github.com/go-kratos/kratos/v2/config/file"
)

c := config.New(
    config.WithSource(
        file.NewSource("/path/to/config.yaml"),
    ),
)
defer c.Close()

if err := c.Load(); err != nil {
    log.Fatal(err)
}

Configuration Sources

Source Interface

config/source.go:11-14
type Source interface {
    Load() ([]*KeyValue, error)
    Watch() (Watcher, error)
}

File Source

Load configuration from files:
import "github.com/go-kratos/kratos/v2/config/file"

c := config.New(
    config.WithSource(
        file.NewSource("/path/to/config.yaml"),
        file.NewSource("/path/to/config.json"),
    ),
)
Supported formats:
  • JSON (.json)
  • YAML (.yaml, .yml)
  • TOML (.toml)
  • XML (.xml)

Environment Source

Load from environment variables:
import "github.com/go-kratos/kratos/v2/config/env"

c := config.New(
    config.WithSource(
        env.NewSource("APP_"), // Prefix for env vars
    ),
)
Environment variables are automatically converted:
  • APP_DATABASE_HOSTdatabase.host
  • APP_SERVER_PORTserver.port

Multiple Sources

Combine multiple sources with merge strategy:
c := config.New(
    config.WithSource(
        file.NewSource("/etc/app/config.yaml"),  // Base config
        file.NewSource("./config.yaml"),          // Override
        env.NewSource("APP_"),                     // Environment overrides
    ),
)

Reading Configuration

Scan Entire Config

config/config.go:135-141
type Config struct {
    Server struct {
        HTTP struct {
            Addr string `json:"addr"`
            Timeout time.Duration `json:"timeout"`
        } `json:"http"`
    } `json:"server"`
}

var cfg Config
if err := c.Scan(&cfg); err != nil {
    log.Fatal(err)
}

log.Infof("HTTP Address: %s", cfg.Server.HTTP.Addr)

Get Specific Values

config/config.go:124-133
// Get string value
addr := c.Value("server.http.addr").String()

// Get int value with default
port := c.Value("server.http.port").Int()

// Get duration
timeout := c.Value("server.http.timeout").Duration()

// Get bool
enabled := c.Value("feature.enabled").Bool()

Value Methods

The Value interface provides type-safe accessors:
val := c.Value("some.key")

// Type conversions
val.Bool() bool
val.Int() int
val.Uint() uint
val.Float() float64
val.String() string
val.Duration() time.Duration
val.Slice() []Value
val.Map() map[string]Value

// Scan into struct
var target MyStruct
val.Scan(&target)

Hot Reload

Watch for Changes

config/config.go:143-149
type Observer func(string, config.Value)

// Watch a specific key
err := c.Watch("server.http.addr", func(key string, value config.Value) {
    log.Infof("Config changed: %s = %s", key, value.String())
    // Reload components that depend on this config
})

Automatic Reload

File and environment sources automatically watch for changes:
c := config.New(
    config.WithSource(
        file.NewSource("/path/to/config.yaml"), // Auto-watches file
    ),
)

c.Load()

// Configuration automatically reloads when file changes

Custom Decoder

import "gopkg.in/yaml.v3"

func yamlDecoder(kv *config.KeyValue, v map[string]interface{}) error {
    return yaml.Unmarshal(kv.Value, &v)
}

c := config.New(
    config.WithDecoder(yamlDecoder),
    config.WithSource(
        file.NewSource("/path/to/config.yaml"),
    ),
)

Custom Resolver

Resolve placeholders in configuration:
func envResolver(input map[string]interface{}) error {
    // Resolve ${ENV_VAR} placeholders
    return nil
}

c := config.New(
    config.WithResolver(envResolver),
    config.WithSource(
        file.NewSource("/path/to/config.yaml"),
    ),
)

Complete Example

config.yaml
server:
  http:
    addr: 0.0.0.0:8000
    timeout: 1s
  grpc:
    addr: 0.0.0.0:9000
    timeout: 1s

data:
  database:
    driver: mysql
    source: root:password@tcp(127.0.0.1:3306)/test

log:
  level: info
import (
    "github.com/go-kratos/kratos/v2/config"
    "github.com/go-kratos/kratos/v2/config/file"
)

type Bootstrap struct {
    Server struct {
        HTTP struct {
            Addr    string        `json:"addr"`
            Timeout time.Duration `json:"timeout"`
        } `json:"http"`
        GRPC struct {
            Addr    string        `json:"addr"`
            Timeout time.Duration `json:"timeout"`
        } `json:"grpc"`
    } `json:"server"`
    Data struct {
        Database struct {
            Driver string `json:"driver"`
            Source string `json:"source"`
        } `json:"database"`
    } `json:"data"`
}

func main() {
    // Create config
    c := config.New(
        config.WithSource(
            file.NewSource("./config.yaml"),
            env.NewSource("APP_"),
        ),
    )
    defer c.Close()

    // Load config
    if err := c.Load(); err != nil {
        log.Fatal(err)
    }

    // Scan into struct
    var bc Bootstrap
    if err := c.Scan(&bc); err != nil {
        log.Fatal(err)
    }

    // Use config
    httpSrv := http.NewServer(
        http.Address(bc.Server.HTTP.Addr),
        http.Timeout(bc.Server.HTTP.Timeout),
    )

    // Watch for changes
    c.Watch("server.http.addr", func(key string, value config.Value) {
        log.Infof("HTTP address changed to: %s", value.String())
        // Implement reload logic
    })

    // Start application...
}

Best Practices

Layer configuration sources from least to most specific: defaults → file → environment.
Scan the entire config once at startup, then watch specific keys that need hot-reload.
Validate configuration after loading to catch errors early.
Always defer Close() to stop watchers and clean up resources.
Check the error when setting up watches - keys must exist before watching.

Logging

Configure logging levels

HTTP Server

Configure HTTP server options

gRPC Server

Configure gRPC server options

Registry

Configure service discovery

Build docs developers (and LLMs) love