
Today most of the application software we develop ends up getting deployed to the cloud & along with it comes its own set of challenges. One such challenge is managing configuration used by our application & separating it from our service logic. Let us consider this over-complicated architecture which we are going to use for our demonstration:

We have a customer facing service WebApp
which clients invoke to get a greeting message. In order to fulfill this request, the WebApp
service performs two operations:
- Calls
Name Service
to get the name part for the greeting - Calls
Greeting Service
to get the greeting in a specific locale
Now both Name Service
& Greeting Service
maintain some configuration which they use for processing the request. In our case the configuration for Name Service
is the value of name used for greeting & configuration for Greeting Service
is the value of greeting in different locales. An example of this can be
greetings:
en: Hello
es: Hola
fr: Bonjour
cn: Nǐ hǎo
jp: Kon'nichiwa
Challenge with co-locating configuration in application code
Let us consider a scenario where we start supporting a new locale for our Greeting Service
or we discover a bug which is leading to incorrect greeting value for certain locale(Eg we missed an o
in en
greeting & now customers are seeing Hell ${customer}
in the response). If the configuration lives within the application code then we have no other choice than to redeploy the service with our code fix even though in our case the fix can be as simple as setting the correct value of a greeting. This also means the incorrect behavior will be extended for the period in which we are doing the redeployment.
Now if we really consider the config for Greeting Service
, it has nothing to do with our service logic. We don’t really care what does the configuration contain & our service flow won’t change based upon what value the config contains. What we really want is an easy mechanism to update the configuration which is independent of our service deployment. So when we notice an incorrect value for our configuration, we just update its value externally without having to redeploy our service to reflect the correct value. With the configuration being externalized our updated architecture looks as below

Exploring techniques for configuration externalization
There are various ways to store & update your external config. Some of them are:
- Version control based configuration
- Filesystem based configuration
- Kubernetes ConfigMaps
All mainstream frameworks provide support for these mechanisms. We are going to look at how we can achieve this using Spring framework. Before diving in let us address another challenge which is pretty evident with our architecture. Right now every service is maintaining its own externalized configuration. This will become pretty challenging once we have to maintain large number of services. Having a centralized way to store & retrieve these configurations can easily abstract away the task of configuration management from our services.
In Spring ecosystem, Spring Cloud config server plays the role of this centralized system. We are going to see it in action while working with both file system as well as version control based configuration. Our updated architecture looks as below:

File system based configuration
Lets start with the simplest mechanism which is the filesystem based configuration. We store the configuration for our services in a filesystem & services can access it during run-time. Now whenever we need to change our configuration, we just need to update the configuration in file system & the config server will pick up the changes. We can now either manually refresh the config for our services by calling an administration endpoint (/actuator/refresh
in case of Spring) or have our services listen for changes in configuration.
Lets go through a demo where our config lives on local file system on path ~config/config.yml
. We can see that we have mistakenly checked in an incorrect value for greeting config & now when user calls our service they get Hell
instead of Hello
which is not so much of a greeting.
Now that we have externalized our configuration to a file system, we can just update the config value in the file system & our config server will pick it up. Once it has updated the config, all the services listening for config changes will be able to read the updated value. In our case it is the greeting service & we can see in the demo that it receives a refresh event & we can now see the correct greeting for our endpoint.
You can find all the code for the file system demo on this branch.
Version control based configuration
We do also need some form of version control & auditing around configuration changes. For this we can make use of version control based configuration where our configs live on a Git server. In our case we are making use of Github repository to store our config. The config server queries the config from Github & then all services can listen to updates from the config server.
Here is the demo for the same where we update the config by adding a commit on the Git repository which sends a web-hook to our config server for refreshing the config. Next the service listening to config changes is able to refresh the config keys & get the updated value at runtime. Also note that the refresh event consist only the delta of changes in order to keep the payload to a minimal.
You can find all the code for Git based config demo on this branch
ConfigMaps
Now when we enter into the Kubernetes world, we no longer need a Spring based config server as ConfigMaps can perform the role of central config storage. All you need to do is to define your config in the ConfigMap & mount the volume on your service pods for them to access the underlying config.
Now when you want to change the config, you can just patch the config or re-apply the yml
file for config & your service pods will have access to the updated config. You can achieve this either by invoking the refresh endpoint or make use of Spring Cloud Kubernetes Configuration Watcher to automatically refresh the config.
You can find all the code for ConfigMap based config on this branch.
Externalizing your application config provides multiple benefits. You can change the application behavior at runtime without doing a fresh deployment. You can also have separate configuration for different environments which can be picked up at run-time using something like a Spring profile. You also get better control over resolving issues which happen due to misconfiguration as now you have decoupled your application from your configuration.
Hope that this was helpful to you. Next I will be covering service registry pattern by doing similar demo using Spring framework. Till then happy learning!