YAML Configuration Deep Dive

Master YAML-based configuration for scalable deployments
Time: 60-75 minutes • Level: Advanced • Prerequisites: Service, Middleware


🎯 What You’ll Learn


📚 Topics

1. Configuration Structure

Understand the YAML schema:

2. Service Definitions

Define and configure services:

3. Router Auto-Generation

Auto-generate routers from services:

4. Middleware Configuration

Configure middleware declaratively:

5. Handler Configurations

Mount handlers at app level:

6. Deployment Topologies

Design multi-deployment setups:

7. Advanced Patterns

Master complex configurations:

8. Database Pools

Configure named database pools:


📂 Configuration Schema

Basic Structure

# Global configuration values
configs:
  app:
    name: "MyApp"
    version: "1.0.0"
  database:
    dsn: "postgres://localhost/mydb"

# Named database pools
dbpool-definitions:
  main-db:
    dsn: "postgres://localhost:5432/mydb"
    schema: "public"
    min-conns: 2
    max-conns: 10

# Middleware definitions
middleware-definitions:
  cors:
    type: cors
    config:
      allowed-origins: ["*"]

# Service definitions
service-definitions:
  user-service:
    type: user-service-factory
    depends-on: [user-repository]
    router:
      convention: rest
      resource: user
      path-prefix: /api/v1

# Router definitions
router-definitions:
  user-service-router:
    convention: rest
    resource: user
    middlewares: [cors]

# External service definitions
external-service-definitions:
  payment-api:
    url: "https://api.payment.com"
    type: payment-client-factory

# Deployments
deployments:
  development:
    config-overrides:
      app:
        debug: true
    
    servers:
      api:
        base-url: "http://localhost"
        apps:
          - addr: ":8080"
            published-services: [user-service]
            
            # Handler configurations
            reverse-proxies:
              - prefix: "/api/v2"
                strip-prefix: true
                target: "http://backend:9000"
            
            mount-spa:
              - prefix: "/admin"
                dir: "./dist/admin"
            
            mount-static:
              - prefix: "/assets"
                dir: "./public/assets"

🔧 Key Features

1. Service Auto-Discovery

Services with @Handler annotation are automatically discovered and registered.

2. Router Auto-Generation

Routers are auto-generated from published services based on metadata.

3. Dependency Injection

Dependencies are resolved automatically from depends-on declarations.

4. Remote Service Resolution

Services published on other servers are automatically configured as remote.

5. Config Variable Resolution

Use ${config.key} to reference config values anywhere.

6. Case-Insensitive Lookups

All names (services, routers, middleware) are case-insensitive.

7. Inline Definitions

Define services/routers inline at deployment or server level for scoped usage.

8. Handler Mounting

Mount reverse proxies, SPAs, and static files directly in YAML.


📖 Configuration Sections

Global Configs

configs:
  app:
    name: "MyApp"
    environment: "production"
  database:
    host: "localhost"
    port: 5432

Reference: ${app.name}, ${database.host}

Named DB Pools

dbpool-definitions:
  main-db:
    host: "localhost"
    port: 5432
    database: "mydb"
    username: "user"
    password: "pass"
    schema: "public"
    min-conns: 2
    max-conns: 10
    max-idle-time: "30m"
    max-lifetime: "1h"
    sslmode: "disable"

Or use DSN directly:

dbpool-definitions:
  main-db:
    dsn: "postgres://user:pass@localhost:5432/mydb"
    schema: "public"

Service Definitions

service-definitions:
  user-service:
    type: user-service-factory
    depends-on:
      - userRepo:user-repository
      - logger:app-logger
    config:
      cache-enabled: true
      cache-ttl: "5m"
    router:
      convention: rest
      resource: user
      path-prefix: /api/v1
      middlewares: [auth, rate-limit]

Router Definitions

router-definitions:
  user-service-router:
    path-prefix: /api/v1
    middlewares: [cors, auth]
    custom:
      - name: GetByEmail
        method: GET
        path: /by-email/{email}
        middlewares: [rate-limit]

Middleware Definitions

middleware-definitions:
  cors:
    type: cors
    config:
      allowed-origins: ["https://app.com"]
      allowed-methods: [GET, POST, PUT, DELETE]
  
  rate-limit:
    type: rate-limiter
    config:
      requests-per-second: 100
      burst: 50

Deployments

deployments:
  production:
    config-overrides:
      app:
        debug: false
    
    servers:
      api-server:
        base-url: "https://api.myapp.com"
        
        # Inline definitions (scoped to this server)
        middleware-definitions:
          custom-auth:
            type: jwt-auth
            config:
              secret: "${JWT_SECRET}"
        
        apps:
          - addr: ":8080"
            routers: [user-service-router]
            published-services: [order-service]

🚀 Handler Configurations

Reverse Proxy

apps:
  - addr: ":8080"
    reverse-proxies:
      # Simple proxy with prefix stripping
      - prefix: "/api"
        strip-prefix: true
        target: "http://backend:9000"
      
      # Proxy with path rewriting
      - prefix: "/graphql"
        target: "http://graphql-server:4000"
        rewrite:
          from: "^/graphql"
          to: "/api/graphql"

Use Cases:

SPA Mounting

apps:
  - addr: ":8080"
    mount-spa:
      # Admin dashboard
      - prefix: "/admin"
        dir: "./dist/admin-spa"
      
      # Main app at root
      - prefix: "/"
        dir: "./dist/main-app"

Behavior:

Static File Serving

apps:
  - addr: ":8080"
    mount-static:
      # Public assets
      - prefix: "/assets"
        dir: "./public/assets"
      
      # Download files
      - prefix: "/downloads"
        dir: "./public/downloads"

Behavior:


🔄 Configuration Loading

Single File

lokstra_registry.RunServerFromConfig("config.yaml")

Multiple Files (Merged)

lokstra_registry.RunServerFromConfig(
    "config/base.yaml",
    "config/services.yaml",
    "config/production.yaml",
)

From Folder

lokstra_registry.RunServerFromConfigFolder("config")

Merge Strategy:


🎯 Best Practices

1. Organize by Concern

config/
├── base.yaml          # Global configs
├── database.yaml      # DB pools
├── services.yaml      # Service definitions
├── middleware.yaml    # Middleware definitions
└── deployments/
    ├── dev.yaml
    ├── staging.yaml
    └── prod.yaml

2. Use Environment Variables

configs:
  jwt:
    secret: "${JWT_SECRET}"
  database:
    password: "${DB_PASSWORD}"

3. Leverage Inline Definitions

deployments:
  production:
    servers:
      api:
        # Server-scoped middleware
        middleware-definitions:
          prod-auth:
            type: jwt-auth
            config:
              secret: "${PROD_JWT_SECRET}"

4. Convention Over Configuration

# Minimal config - uses conventions
service-definitions:
  user-service:
    type: user-service-factory
    depends-on: [user-repository]
    router: {}  # Auto-generates from metadata

5. Explicit When Needed

# Explicit config - full control
service-definitions:
  user-service:
    type: user-service-factory
    depends-on: [user-repository]
    router:
      convention: rest
      resource: user
      path-prefix: /api/v1
      middlewares: [cors, auth]
      hidden: [Delete]
      custom:
        - name: GetByEmail
          path: /by-email/{email}

📂 Examples

All examples are in the examples/ folder:

01 - Basic Configuration

Simple single-file configuration.

02 - Multi-File Merging

Split configuration across multiple files.

03 - Service Dependencies

Complex dependency injection.

04 - Router Customization

Advanced router configuration.

05 - Multi-Deployment

Development, staging, production setups.

06 - Handler Configurations

Reverse proxy, SPA, and static file mounting.

07 - Database Pools

Named database pool configuration.

08 - Environment Variables

Environment-based configuration.


🚀 Quick Start

# Run any example
cd docs/02-framework-guide/04-config/examples/01-basic-config
go run main.go

# Test with provided test.http

📖 Prerequisites

Before diving in, make sure you understand:


🎯 Learning Path

  1. Understand structure → Learn YAML schema
  2. Define services → Configure dependency injection
  3. Generate routers → Auto-generate from services
  4. Configure middleware → Apply at different levels
  5. Mount handlers → Add proxies, SPAs, static files
  6. Design deployments → Multi-environment setups
  7. Merge configs → Split across files
  8. Use env vars → Environment-based config

💡 Key Takeaways

After completing this section:



Next: App & Server Deep Dive →