Better Configuration Files

Over the years I have seen many configuration files. Most of them were unusable. There are many reasons for unusable configuration files. What I've learned from looking at large configurations are those main points:

1. Values

Often configuration files use the wrong values. Developers tend to use true/false for switching options on and off.

track-users = true

The configuration is easier to understand when instead of true/false one uses on/off, it's more relevant to the domain

tracking-users = on

Sometimes there are double negations like

no-track-users = true

which leads easily to wrong configurations and is harder to understand. This also leads to inconsistencies like

track-users = on
no-paypal = off
creditcard = on

Do not use double negation, best stick with positive switches where possible.

2. Lists and Types

I'm a friend of typing data. This also goes for configuration values. Your configuration system should support simple types like Strings, Numbers and Lists.

backends = ['backend1', 'backend2', 'backend3']
port = 8080
name = "TestDB"

Then a configuration checker can check the values for typos, like

port = 808x0
backends = ['backend1' 'backend2', 'backend3']
// backends = backend1 backend2, backend3

Lists make configuration files easier to read and shorter. If you have no List support, configurations tend to look like this:

backend.1 = backend1
backend.2 = backend2
backend.3 = backend3
currency = dollar
currency = euro

Compare this to the clean List code above.

3. Descriptive

Configuration options should be descriptive. Often they tend to use lots of true/false configuration switches.

database = true
redis = false
cassandra = false

If possible, its better to replace true/false switches with possible options:

database = REDIS

4. Hierarchical configurations

Flat configurations are hard to read. To group configuration keys with flat configurations you need to repeat yourself with namespace values. I know many do not like mixing property style and XML style, but I've learned that this works really well for configurations (YAML is another hierarchical option).

    server =
    port = 8080
    name = "TestDB"

is more readable and clear than

database.server =
database.port = 8080 = "TestDB"

or even

ordermanagement.database.server =
ordermanagement.database.port = 8080 = "TestDB"

5. Application configuration, server instances and environments

The configuration for one of your application instances is a combination of the environment the instance runs, the application configuration and the server instance.

// application code
database-url = jdbc://$DATABASE.server//$DB
callback-url = http://$HOST/callback

Both database-url and callback-url are application configuration values, $DB is depending on the environment (development, production, test) and $HOST is depending on the server instance. Environment solution can easily be done in different configuration files, e.g. put them into production, development and test directories. This enables you to put all configurations into your source control system.

6. Inversion of control and DRY

Your configuration framework should support inversion of control or dependency injection, I'm not sure what to call it. Do not define the database server IP in every client, define it in the database server configuration and inject/reference it into every client configuration.

// database server config
host = $HOST

and the client

// client config
database.server = $

instead of

// client config
database.server =

Client does not declare the database server, the client determines at startup the runtime config by getting the values from the database server. This can most easily solved with a configuration service, it's harder to solve with configuration files.

7. Write a configuration checker

Of utmost importance is to write a configuration checker. Many production problems arise from wrong configurations. Apache supports a config test before you restart the application by running

apachectl configtest

The checker should check typos, not resolved dependecies, not resolved variables, type checks (String, Number, List, IP, ....) and mandatory values.


Writing configuration in the wrong way leads to maintenance and production problems. Do not neglect the configuration of your application, you need to put thought into it or it will turn to an unmanageable mess.

Stephan Schmidt Administrator
CTO Coach , svese
Stephan is a CTO coach. He has been a coder since the early 80s, has founded several startups and worked in small and large companies as CTO. After he sold his latest startup he took up CTO coaching. He can be found on LinkedIn or follow him in Twitter.
follow me