Skip to content

Migrate Configuration Format from YAML to TOML #634

@renuka-fernando

Description

@renuka-fernando

Discussed in #633

Originally posted by renuka-fernando January 6, 2026

Summary

This proposal discusses migrating our gateway configuration from YAML to TOML format. The primary motivation is to improve configuration maintainability and reduce indentation-related errors.

Current State

Our configuration file (gateway/configs/config.yaml) is a 364-line YAML file with deep nesting (up to 4-5 levels). Key sections include:

  • gateway_controller.server
  • gateway_controller.policyserver.tls
  • gateway_controller.router.downstream_tls
  • gateway_controller.router.policy_engine.tls
  • policy_engine.xds.tls
  • analytics.publishers[].settings

Problems with Current YAML Configuration

1. Indentation Sensitivity

YAML's strict indentation requirements make configuration error-prone. A single misaligned space can cause:

  • Silent parsing failures
  • Unexpected configuration merging
  • Hard-to-debug runtime errors

Example from our config:

gateway_controller:
  router:
    policy_engine:
      tls:
        enabled: false
        cert_path: ""    # Must be exactly 8 spaces
        key_path: ""     # One wrong space = broken config

2. Copy-Paste Friction

When adding new configuration sections, users must:

  1. Find the correct location in the hierarchy
  2. Calculate the exact indentation level
  3. Carefully paste while preserving whitespace
  4. Manually adjust if the source had different indentation

This is particularly problematic when copying configuration examples from documentation.

3. Implicit Type Conversion

YAML silently converts values based on content, which can cause unexpected behavior:

# These are interpreted differently:
port: 9090      # Integer
port: "9090"    # String
enabled: yes    # Boolean (true)
enabled: "yes"  # String
version: 1.0    # Float
version: "1.0"  # String

Our config has several values that could be misinterpreted (ports, timeouts, versions).

4. Deep Nesting Becomes Unreadable

Current nesting example:

gateway_controller:
  router:
    envoy_upstream:
      tls:
        minimum_protocol_version: TLS1_2
        maximum_protocol_version: TLS1_3
        ciphers: "ECDHE-ECDSA-AES128..."

Users must trace 4 levels of indentation to understand the context.

Proposed Solution: TOML

What is TOML?

TOML (Tom's Obvious, Minimal Language) is a configuration format designed to be:

  • Simple and readable
  • Predictable (no whitespace sensitivity)
  • Explicit (clear type definitions)

It's used by modern tools including Cargo (Rust), pyproject.toml (Python), Hugo, and many Go projects.

Benefits of TOML

1. Indentation Independence

Copy-paste anywhere - Users can add configuration sections without worrying about indentation:

[gateway_controller.router.policy_engine.tls]
enabled = false
cert_path = ""
key_path = ""
ca_path = ""

Indentation is purely cosmetic and ignored by the parser.

2. Explicit Section Headers

Clear visual separation between configuration sections:

[gateway_controller.server]
api_port = 9090
xds_port = 18000
shutdown_timeout = "15s"

[gateway_controller.policyserver]
enabled = true
port = 18001

[gateway_controller.policyserver.tls]
enabled = false
cert_file = "./certs/server.crt"
key_file = "./certs/server.key"

3. Type Safety

TOML requires explicit syntax for types:

port = 9090              # Always integer
port_str = "9090"        # Always string
enabled = true           # Always boolean (no "yes"/"no" ambiguity)
timeout = "15s"          # Always string

4. Easier Navigation

Section headers act as natural anchors. Users can search for [gateway_controller.router.policy_engine] directly instead of counting indentation levels.

5. Better Tooling Support

  • Most modern editors have TOML syntax highlighting
  • Go has excellent TOML libraries (github.com/BurntSushi/toml, github.com/pelletier/go-toml)
  • IDE schema validation works well with TOML

Example: Current YAML vs Proposed TOML

Current YAML:

gateway_controller:
  server:
    api_port: 9090
    xds_port: 18000
    shutdown_timeout: 15s

  policyserver:
    enabled: true
    port: 18001
    tls:
      enabled: false
      cert_file: "./certs/server.crt"
      key_file: "./certs/server.key"

  router:
    gateway_host: "*"
    listener_port: 8080
    https_enabled: true
    https_port: 8443

    downstream_tls:
      cert_path: "./listener-certs/default-listener.crt"
      key_path: "./listener-certs/default-listener.key"
      minimum_protocol_version: TLS1_2
      maximum_protocol_version: TLS1_3

Proposed TOML:

[gateway_controller.server]
api_port = 9090
xds_port = 18000
shutdown_timeout = "15s"

[gateway_controller.policyserver]
enabled = true
port = 18001

[gateway_controller.policyserver.tls]
enabled = false
cert_file = "./certs/server.crt"
key_file = "./certs/server.key"

[gateway_controller.router]
gateway_host = "*"
listener_port = 8080
https_enabled = true
https_port = 8443

[gateway_controller.router.downstream_tls]
cert_path = "./listener-certs/default-listener.crt"
key_path = "./listener-certs/default-listener.key"
minimum_protocol_version = "TLS1_2"
maximum_protocol_version = "TLS1_3"

Handling Arrays (e.g., Publishers)

Current YAML:

analytics:
  publishers:
    - type: moesif
      enabled: true
      settings:
        application_id: <MOESIF_APPLICATION_ID>
        publish_interval: 5

Proposed TOML:

[[analytics.publishers]]
type = "moesif"
enabled = true

[analytics.publishers.settings]
application_id = "<MOESIF_APPLICATION_ID>"
publish_interval = 5

Considerations

Potential Drawbacks

Concern Mitigation
Less common in cloud-native ecosystem (K8s uses YAML) We're not Kubernetes; our config is for our own services
Team familiarity with YAML TOML has simpler spec; learning curve is minimal
Arrays look more verbose Trade-off for clarity and reduced errors

Implementation Notes

  • Go configuration libraries (Viper, Koanf) support TOML natively
  • We already use Koanf which has TOML support via koanf/parsers/toml
  • Schema validation can be maintained with struct tags

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    Area/GatewayAny issues related to API deployment in gateway, routing etc.

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions