I find that we ask this question far too many times when talking to developers. While we allow ourselves to go fast and break things, we also need to realize that in doing so, we’re often taking on technical debt. As architects, when conducting a code review or we sense that someone is taking a shortcut, asking this question is always key.
If a key element of an application is not configurable its often something that’s hard coded into the application itself. In many cases changing crucial behavior will require a complete CICD pipeline execution which takes time and can often disrupt users if not planned carefully. Its often much simpler to think about configuration as an underlying functional requirement. In some cases, investing in and constructing configuration control planes and behavior into code may be untenable given date and service window requirements. At that point, we need to decide if we’re going to take on the technical debt now and reduce it later. Maybe there’s a speed versus manageability tradeoff that is made. It might be alluring to hardcode, as you’ll know exactly what’s in production, but that will lead to future pain when things change--and things will change.
Configuration is another tool in the toolbox for changing the behavior of an application. However, this does require a holistic design cycle (non-functional design) ahead of time. However as much as we’d like to anticipate every instance where configuration will be required, there will be those scenarios where unanticipated “hard coding” must or does take place. It’s important that we don’t go overboard and make everything configurable. You also need to be careful in not making the app overly configurable because then you can slow it down at runtime and introduce configurability bugs. So really, there’s a spectrum of choices and ideally, you’ll want to design to land somewhere in the middle.
Dynamic behavior and ever-changing environments require configurability and your ability to cope with it. The ideal method is to read the configuration once at startup and then cache it. You don’t go and check too frequently, but maybe set up a timer within the app that says if nothing happens, check every 24 or 48 hours. In other words, design it to be as configurable as possible and then run it as statically as possible.
You should ensure that you can forcibility expire a cache, so when you do have emergency changes, you can implement those changes and your app isn’t ignoring after changing values.
Remember that configurations are software artifacts, and they need to be managed as such. Make sure to use your DevOps tool of choice to verify the configuration and other metadata about your application. GitOps is a good example of an emerging capability that represents this trend. You need to version control the configuration and diff the latest and previous versions.
This was another great session with Eric and Uli! If you’d like to learn more, check out the video below! Be sure to look out for more videos and posts in the near future.