Skip to content

Configuration Hierarchy

CAP provides a powerful and flexible configuration system that allows you to define a base configuration and then override it for specific instances or environments. Understanding this hierarchy is key to managing your application deployments efficiently.

The Merge Order

CAP merges configurations from different levels in a specific order. Settings from later levels take precedence over and override settings from earlier levels.

The merge order is as follows:

  1. Top-Level config.cap.yaml: The default settings in your application's config.cap.yaml that are not nested under instances or environments.
  2. Global environments Block: Settings from the top-level environments block that match the current deployment environment. This allows you to define global settings for all production or staging deployments, regardless of the instance.
  3. Instance-Level Config: Settings defined within a specific instance in your config.cap.yaml (e.g., under instances.nl).
  4. Instance-Specific environments Block: Settings defined within an environment nested inside an instance (e.g., instances.nl.environments.production). This is the final and most specific level of configuration.

The merging is recursive for objects and dictionaries. For example, if you define http.replicas at the top level and http.port at the environment level, the final http block will contain both replicas and port. However, if you define the same property at multiple levels, the value from the most specific level is used.

Warning

For index-based arrays (like whitelist and connections), merges will override existing keys. We do not recommended merging these at this time.

Detailed Example

Let's walk through a complete example to see how the hierarchy works.

config.cap.yaml

# 1. Top-level defaults
http:
  replicas: 1
  port: 8080
env:
  APP_NAME: "My Awesome App"

# 2. Global environments block
environments:
  production:
    # This applies to ALL production environments
    env:
      APP_DEBUG: false
      LOG_LEVEL: "error"

# 3. Instances block
instances:
  nl:
    hostname: "my-app.nl"
    http:
      replicas: 2 # Overrides top-level

    # 4. Instance-specific environments
    environments:
      staging:
        # inherits nl instance config

      production:
        hostname: "www.my-app.nl" # Overrides instance-level hostname
        http:
          replicas: 10 # Overrides instance-level replicas
        env:
          APP_LOCALE: "nl_NL" # Merged with global production env

  be:
    hostname: "my-app.be"
    # Inherits top-level replicas: 1

    environments:
      production:
        hostname: "www.my-app.be"
        # Also inherits top-level replicas: 1
        # Merged with global production env

Final Configuration for nl instance, production environment:

CAP merges: Top-Level -> Global production -> Instance (nl) -> Instance production.

# Final merged config for nl-production
http:
  replicas: 10      # From instance 'nl' production env (most specific)
  port: 8080        # From top-level
env:
  APP_NAME: "My Awesome App"  # From top-level
  APP_DEBUG: false      # From global production env
  LOG_LEVEL: "error"    # From global production env
  APP_LOCALE: "nl_NL"   # From instance 'nl' production env
hostname: "www.my-app.nl" # From instance 'nl' production env

Final Configuration for be instance, production environment:

CAP merges: Top-Level -> Global production -> Instance (be) -> Instance production.

# Final merged config for be-production
http:
  replicas: 1       # From top-level (instance 'be' did not override it)
  port: 8080        # From top-level
env:
  APP_NAME: "My Awesome App"  # From top-level
  APP_DEBUG: false      # From global production env
  LOG_LEVEL: "error"    # From global production env
hostname: "www.my-app.be" # From instance 'be' production env