Most application, services, app, program, whatever has some kind of configurations. Some of the them are visible to the user, some of them are only available to the provider, some of them might be derived from other settings.
In larger applications, like web services and stuffs, configurations play a huge role. No one wants to recompile the whole program when there are needs to move the log file location, for example. Well-implemented applications provides numbers of configuration, so they are flexible enough to handle different environments and usages.
Below is what I think it should be taken in consideration when designing configuration management.
Configuration implementation is ‘details’.
There are multiple way to keep and to read the configuration. It could be an in-memory objects, SQLite, SQL server, No-SQL server, Redis, or even a configuration server. Regardless, this should be considered as a ‘detail’. The application should not aware of how these operations work. It should be able to query the configuration through an interface which is opaque to it.
The application should be able to switch between implementations without much change down in the application code. If the architecture is designed well, switching between implmentation should not takes more than 10 LOC changes, excluding the interface implmentations.
It might be a plus to be able to switch the implementations without changing code. However, this usually come with complications (eg. another separated set of configuration in another configuration implementation). Consider the complication and choose wisely wheter or not it needs to be that flexible. Usually applications do not need to change the configuration implementation very often.
Treat Configuration separately from Data.
Configuration should not be treated like a data. It controls how the application work, as opposed to data which the application operated on.
By its nature, data is incrementally changed over time. After application is used for quite some time, amount data will grow. Configurations, in the other hand, does not get increased as much. Most of the time it stay the same, and occasionally updated to accomodated business need. Configuraions only increases when there is a new capability added to the application.
Because of how often the data is updated, its not advisable to keep every single version of data. It just simply too many. What can be done is to log the operations made to the data, which can be later traced by developer when something bad happens. Also having a snapshot periodically helps to quickyly restore the data back to the proper state.
However, since configuration is rarely changed, it’s quite easy to track every single version of the configuration. For instance, we can put the configuration source in an version control system.
Keep number of the configuration sources low.
Configuration is needed to be loaded in some kind of source. Here, I’ll call it a configuration source. It could be simply a configuration file, or may be a configuration server. Again, the implementation is just a detail.
Anyway, one thing to consider is there should not be too many sources. In best case scenario, one universal source is prefered. This source should keep every single configuration, as it is easier to track changes.
In some scenario, there might be needs for ‘configuration overide’ which settings from one source override another. Be mindful about designing the policy. There should not be too many level of override, as it creates ‘dependencies’ between them. From my personal experience, 2-3 level is acceptable, larger than that it might be too many. Also having multiple source of truth creates confusions in the developers and operator. It will hurt everyone in the team in the long run.
Having multiple sources that incrementally change the configuration is unadvisable. The reason is it creates multiple level of dependency. Configuration sources have to be load in an correct order, otherwise the configuration will be incorrectly loaded.