My favorite patterns: Limiting Configuration

Dave
3 min readFeb 5, 2019

Or: Why “less is more” when it comes to configuration.

This continues my series on my favorite application/design patterns, where I describe underrated patterns that have worked for me in the past, and that make me happy.

You could argue that this isn’t a pattern per se. The short version is something like “don’t put everything in configuration, just hard-code it.”

So, what is configuration? Many apps have some JSON like this in a config file, or environment variables that determine the behavior of the system, and stores some data that’s required for the system to run properly.

In the listing above you’ll see a setting for logging, a connection string, and API key and URL for some integrated service. You’ll also see a name for the service, a feature toggle (`enableSweetNewFeature`) and a value that’s probably used in an abstract factory to determine which algorithm to use at runtime (`vendorSelectionImplementation`).

Hopefully you’re looking at that and nodding, like you’ve seen all this before.

Just because you can doesn’t mean you should

Why do we do this? I believe there are three reasons we historically put code in configuration:

  1. When certain parameters to the running application differ per environment
  2. When certain data is sensitive in nature and thus should not be committed with the source code
  3. When config data needs to be updated at runtime (without redeploying the application).

I believe that the first two reasons are valid reasons to store data in configuration, but the third is not.

Human-readable configuration was born in a time when deploying an application was time-consuming and rare. Releases were scheduled, and the whole team was “on-deck.” Often they were on weekends so users wouldn’t be disrupted.

But that was then, and this is now. This is the age of DevOps and continuous delivery. Changing running software, in today’s world, should be trivial.

But that was then, and this is now. This is the age of DevOps and continuous delivery. Changing running software should be trivial.

If we look at our configuration settings above through this lens, some seem appropriate, while others don’t.

  • Connection strings: probably change per environment and should be secured, so should not be compiled into the code 👍
  • API keys and base URLs for integrated services: also probably change per environment and should be secured 👍
  • Feature toggles: while this is reasonable, I’d argue it’s best to use a specific library or service for this like LaunchDarkly. But we’ll give it a begrudging 👍
  • Application-specific data: you’ll see that the application name is here. It’s really useful to have that for logging/monitoring. Perhaps even some framework-level code expects that setting. But this should be hard-coded 10 out of 10 times 👎
  • Settings for how the object runs: sometimes you want to choose a different algorithm for a key business process, or something similar. Honestly, just hard-code this. How often are you really updating this at run-time? 👎

There are two issues at play here. Not only should changing and re-deploying the code be just as easy as pushing a commit, but if your app is deployed across multiple servers or in some serverless PaaS, it’s actually harder to update the config file than it is to push new code.

Configuration is state. In my experience the stateful aspect of applications is the hardest thing about running them in multiple environments. Your code is in one state, your config files are in another, and your database schema is in another. Hope they match! Applications don’t like not being able to find their config values, or running against a DB schema they’re not expecting. This means that your code is tightly coupled with your config/schema, and you need to make sure they are updated in lockstep. This means more sophisticated patterns (blue/green deployments, backward-compatible code) are required.

You know where all this is going: it means it’s probably best to minimize the number of independent pieces of statefulness in your system.

You want to minimize the independent loci of state in your system.

In conclusion

Configuration files are, to some extent, a relic of on-premise, server-based computing. In a modern web-based application, their use should be constrained as much as possible. The files are deployed with the code, and the data should be immediately converted to strongly-typed data anyway, so why not just do it in the code?

Further reading

--

--