Features

Each feature below starts with a situation you have probably lived through, then shows the configuration before and after Microconfig. Every example uses the same two services from the quickstart, so you can run it yourself.

The full reference is in the documentation.

Simple Configuration Layout

Real life: A new team ships a new service. Instead of copying a neighbour's 300 lines, they create a folder next to their other services, include what the company agreed on and add only what is unique. With Microconfig, folders are just folders: group them by team, domain or anything else.

How Microconfig solves it

Put each service in its own folder anywhere under components/, grouped by team, domain or anything else. Folder names are up to you. Different config types of one service, like application.yaml and values.deploy, live side by side in its folder.


                        components
                        ├── payments
                        │   ├── payment-backend
                        │   │   ├── application.yaml
                        │   │   └── values.deploy
                        │   └── payment-frontend
                        │       ├── application.yaml
                        │       └── values.deploy
                        └── ...
                        ...
                    

Reuse Common Parts

Real life: Your Kafka cluster moved to a new address, and 50 services have it copy-pasted. Someone will miss one. With Microconfig, connection settings live in one shared component: change one file and every service that includes it gets the new address on the next build.

How Microconfig solves it

Move a shared block to its own component and add #include monitoring, logging to every service that needs it. Service configs keep only what is unique to them, and an update to the shared block reaches every service on the next build. A service can still override any included value.

payment-backend

                                        
                                        name: payment-backend

                                        server:
                                          port: 8080
                                          context: /api

                                        monitoring:
                                          secure: false
                                          base-path: /monitoring
                                          endpoints: info, health, ready, prometheus

                                        logging:
                                          level:
                                            ROOT: INFO
                                            APP: DEBUG
                                        
                                    

payment-frontend

                                        
                                        name: payment-frontend

                                        payment-backend:
                                          host: http://payment-backend.local
                                          path: /api

                                        monitoring:
                                          secure: true
                                          base-path: /monitoring
                                          endpoints: info, health, ready, prometheus

                                        logging:
                                          level:
                                            ROOT: INFO
                                            APP: DEBUG
                                        
                                    

payment-backend

                                        
                                        name: payment-backend

                                        server:
                                          port: 8080
                                          context: /api

                                        #include monitoring, logging
                                        
                                    

payment-frontend

                                        
                                        name: payment-frontend

                                        payment-backend:
                                          host: http://payment-backend.local
                                          path: /api

                                        #include monitoring, logging

                                        monitoring:
                                          secure: true
                                        
                                    

monitoring

                                        
                                        monitoring:
                                          secure: false
                                          base-path: /monitoring
                                          endpoints: info, health, ready, prometheus
                                        
                                    

logging

                                        
                                        logging:
                                          level:
                                            ROOT: INFO
                                            APP: DEBUG
                                        
                                    

Reference Values

Real life: The backend moved its API from /api to /api/v2. Nobody told the frontend, and it broke in production. With Microconfig, the frontend references the backend's value instead of copying it, so both change together.

How Microconfig solves it

Reference a value instead of copying it: ${payment-backend@server.context} reads server.context from the backend's config, ${this@name} from the current one. The value lives in one place, the dependency is explicit, and a reference to a missing component or key fails the build.

payment-backend

                                        
                                        name: payment-backend

                                        server:
                                          port: 8080
                                          context: /api

                                        ...
                                        
                                    

payment-frontend

                                        
                                        name: payment-frontend

                                        payment-backend:
                                          host: http://payment-backend.local
                                          path: ${payment-backend@server.context}

                                        ...
                                        
                                    

payment-frontend

                                        
                                        name: payment-frontend

                                        payment-backend:
                                          host: http://payment-backend.local
                                          path: /api

                                        ...
                                        
                                    

Dynamic Values

Real life: timeoutMs: 180000. Is that 3 minutes or 30? With Microconfig, you write #{3 * 60 * 1000} and the next person reading the config doesn't need a calculator.

How Microconfig solves it

Write values as expressions with #{...}: arithmetic like #{3 * 60 * 1000}, string functions like toUpperCase(), and placeholders inside them. The generated file gets the plain result.

payment-frontend

                                        
                                        name: payment-frontend

                                        payment-backend:
                                          timeoutMs: 180000

                                        log:
                                          filename: PAYMENT-FRONTEND.log

                                        ...
                                        
                                    

payment-frontend

                                        
                                        name: payment-frontend

                                        payment-backend:
                                          timeoutMs: #{ 3 * 60 * 1000 }

                                        log:
                                          filename: #{ '${this@name}'.toUpperCase() }.log

                                        ...
                                        
                                    

Environment Specific Config

Real life: A client needs their own stage by tomorrow. Copying 50 service configs and editing database hosts by hand takes a day and invites mistakes. With Microconfig, a new environment is one small file that overrides only what differs.

How Microconfig solves it

Keep the base config in application.yaml and only the differences in application.dev.yaml or application.prod.yaml next to it. Microconfig merges them for each environment, and the more specific value wins. A new environment is one file in envs/ plus overrides where it differs.

payment-backend dev

                                        
                                        name: payment-backend

                                        payment-gateway: http://gateway-mock.local

                                        database:
                                          type: Postgres
                                          pool-size: 10
                                          url: jdbc:postgres://10.10.10.10:5432/database

                                        ...
                                        
                                    

payment-backend prod

                                        
                                        name: payment-backend

                                        payment-gateway: https://payment-gateway.com

                                        database:
                                          type: Postgres
                                          pool-size: 50
                                          url: jdbc:postgres://20.20.20.20:5432/database

                                        ...
                                        
                                    

payment-backend/application.dev.yaml

                                        
                                        payment-gateway: http://gateway-mock.local

                                        database:
                                          host: 10.10.10.10
                                        
                                    

payment-backend/application.prod.yaml

                                        
                                        payment-gateway: https://payment-gateway.com

                                        database:
                                          host: 20.20.20.20
                                          pool-size: 50
                                        
                                    

payment-backend/application.yaml

                                        
                                        name: payment-backend

                                        database:
                                          type: Postgres
                                          pool-size: 10
                                          url: jdbc:postgres://${this@database.host}:5432/database
                                        
                                    

Static Files Templating

Real life: Every service needs its own logback.xml, and only prod should ship logs to Logstash. Fifty almost-identical XML files drift apart. With Microconfig, you keep one template and each service gets its own version with its name and environment settings filled in.

How Microconfig solves it

Keep one template, for example logback.xml, with placeholders like ${this@name} and Mustache sections for the parts that only some environments need. Microconfig renders a separate file for every service and environment.

payment-backend log config dev

                                        
                                        <configuration>
                                          <appender class="FileAppender">
                                            <file>logs/payment-backend.log</file>
                                            <encoder>
                                              <pattern>%d{HH:mm:ss} %-5level %logger %msg %n</pattern>
                                            </encoder>
                                          </appender>
                                        </configuration>
                                        
                                    

payment-backend log config prod

                                        
                                        <configuration>
                                          <appender class="FileAppender">
                                            <file>logs/payment-backend.log</file>
                                            <encoder>
                                              <pattern>%d{HH:mm:ss} %-5level %logger %msg %n</pattern>
                                            </encoder>
                                          </appender>

                                          <appender class="LogstashTcpSocketAppender">
                                            <destination>30.30.30.30:9600</destination>
                                            <encoder class="LogstashEncoder">
                                              <customFields>{"servicename":"payment-backend"}</customFields>
                                            </encoder>
                                          </appender>
                                        </configuration>
                                        
                                    

log template.xml

                                        
                                        <configuration>
                                          <appender class="FileAppender">
                                            <file>logs/${this@name}.log</file>
                                            <encoder>
                                              <pattern>%d{HH:mm:ss} %-5level %logger %msg %n</pattern>
                                            </encoder>
                                          </appender>

                                        {{#appender.stash}}
                                          <appender class="LogstashTcpSocketAppender">
                                            <destination>30.30.30.30:9600</destination>
                                            <encoder class="LogstashEncoder">
                                              <customFields>{"servicename":"${this@name}"}</customFields>
                                            </encoder>
                                          </appender>
                                        {{/appender.stash}}
                                        </configuration>
                                        
                                    

payment-backend prod

                                        
                                        mc.mustache.log:
                                          fromFile: ${log@configDir}/template.xml
                                          toFile: logback.xml

                                        name: payment-backend

                                        #var appender.stash: true
                                        ...
                                        
                                    

Config Diff

Real life: It's Friday, the release goes out in an hour, and someone asks: “What changes in prod config this time?” With Microconfig, every build writes a git-style diff next to each service's configs: added, removed and changed properties, ready to review.

How Microconfig solves it

Every build compares the new files with the previous build in the same output folder and writes diff-application.yaml and similar files next to them: added, removed and changed properties for each service.

payment-frontend v1

                                        
                                        name: payment-frontend

                                        monitoring:
                                          base-path: /monitoring
                                          endpoints: info, health, ready, prometheus

                                        payment-backend:
                                          host: http://payment-backend.local
                                          path: /api

                                        server:
                                          maxThreads: 100
                                          minThreads: 10
                                          port: 80
                                          timeoutMs: 180000
                                        
                                    

payment-frontend v2

                                        
                                        name: payment-frontend

                                        monitoring:
                                          base-path: /monitoring
                                          endpoints: info, health, ready, prometheus

                                        payment-backend:
                                          host: https://payment-backend.local
                                          path: /api
                                          timeoutMs: 180000

                                        server:
                                          port: 80
                                        
                                    

payment-frontend diff between v1 and v2

                                        
                                        +payment-backend:
                                          timeoutMs: 180000

                                        -server:
                                          maxThreads: 100
                                          minThreads: 10
                                          timeoutMs: 180000

                                        payment-backend:
                                          host: http://payment-backend.local -> https://payment-backend.local
                                        
                                    

More in the documentation

Want to see it on your machine? The quickstart takes about 2 minutes: install, build, change one line and see every service update.

Try it in 2 minutes →