In ConfigHub, the startup I founded with Brian and Alexis, we’re building a new kind of configuration storage using a plain old database instead of git.

Git has become the dominant way to store software deployment configuration because it has some nice things that you need:

  • It is versioned (duh)

  • Config became increasingly declarative (k8s, terraform, cloudformation, etc), which represents well as files

  • There are cloud services available for hosting it which come with rich collaboration and workflow tools

Git is great for managing something that is truly a file. But deployment configuration just masquerades as files. In reality it is a graph-shaped data structure that describes a set of live systems, e.g. your dev, staging and production clusters.

You can get pretty far with git, but it just isn’t a great tool to manage a data graph. There are much better tools for that, such as a graph database or a plain old SQL database with a graph schema and some JSON capabilities (hello Postgres).

Git frictions

Where do we run into friction with git?

Relationships

Let’s use the simplest example of a k8s deployment that needs access to a database. The deployment needs a DB_HOST environment variable to connect to the database. The database is a managed service, so this hostname is provided by the service provider (e.g. AWS RDS) once the database is provisioned. The hostname can change, e.g. if you re-provision a new database from a snapshot.

In git, we solve this with something like ${database.host} variable interpolation. But that just means that git is no longer the source of truth for the actual configuration. The actual hostname is stored somewhere else, e.g. in a terraform state file or some key/value store. You can’t check referential integrity with git alone. You don’t have a single place to audit changes to your configuration.

In a database, you can represent the relationship between the deployment and the database. You can store the hostname as a “fact” about the deployed database and link to it from the deployment. You will know when this value changes. You can surface staleness. You can decide to automatically remediate (auto-update the deployment and apply the change), or fire an alert. You have a complete audit trail of what is happening at the right level of granularity.

Granularity

Speaking of granularity. Git imposes granularity on you in terms of files and repos. In theory, you can have very small or very large git repos. But in reality, you are constrained by the tooling available to you. If you use Github, there is a complexity cost to having 1000s of repos. But if you have just a few repos, then you don’t have good access control.

It is not ideal to have this kind of granularity imposed on deployment configuration when it really should be treated as a single data graph with granular access controls.

You are forced to separate your prod config from non-prod because you want to constrain access to it and now you have made it harder for changes to flow naturally from non-prod to prod.

Or you force teams to raise a ticket to get a new environment up and running because the granularity constraint prevents you from giving them self-service access.

When config is stored in a database, you can have the same kind of access control that you have for your CRM or HR system or Google Docs. Teams can self-service create new variants of existing components (deployed only to the environments they’re allowed to touch). There is no need to artificially divide up the config just for access control reasons.

Distributed versioning

One of the greatest powers of git is its distributed versioning capabilities. Developers can work for long periods of time in different branches and then merge or rebase later on. This is great for software development and it works because you are working on a collection of “dead” files.

When you use git for deployment configuration, the files in the repo describe the state of a specific live system. There is not a live system for every distributed copy of the repo. Distributed copies are meaningless. But this distribution is deeply engrained in git and that creates an impedance mismatch.

We usually solve this by only caring about one centralized copy of the repo (e.g. main branch in github). But we still have to deal with the awkwardness of using pull requests to “deploy”. Do I deploy before I merge or after? Git can get the job done. But it is not the best tool.

A database is a more natural fit. With a database, you can create the right model for the job and you have clear centralized and transactional control over changes. You can cleanly model the intended live state and separately track change sets that span any slice of the full config graph.

Field level control

Git is file based and line based when diffing. This makes it a pretty decent tool for tracking changes to deployment configuration stored as files.

But with a proper config graph data store, you can make changes and track changes at the field level. A line has little semantic meaning in a config data structure. What you care about is that the image tag was updated from v1.4.2 to v1.4.3, who did it, who approved it, and when was it rolled out. And in many cases, this is a bulk change over a pattern. E.g. update to v1.4.3 for all environments labeled “non-prod”.

The full intent can easily be captured when you use a database and you combine with higher level functions for making changes, e.g. a “set-image to X where label = …” function. In git this shows up as just a set of file changes with line diffs and possibly across multiple repos with multiple PRs. Sure you can live with that, but what if you didn’t have to?

Comparables

We have gotten so used to using git to manage deployment config that we don’t really consider alternatives.

But think about managing your HR system as a git repo, or your order management system, or your CRM system. These are all business databases with some typical characteristics: single source of truth, transactionality, multi-dimensional views, fine grained access controls, audit trails, data relationships and integrity controls, workflows, etc. A file based, distributed version control tool like git is not the right tool for these jobs.

If you take a step back, it feels obvious that your software deployments deserve the same thing. And we know that software is not just a peripheral concern. After all, isn’t every company a software company? Isn’t software eating the world? Why would you manage such an important part of your business with a tool that is clearly not cut out for the job?

Change Pressure

Software deployment is an operational discipline and change does not come quickly to operations. It’s easy enough to add a new feature to a software library and release a new version. My tests passed! It’s much harder to upgrade a running system to that new version when your business and its customers depend on it.

Changing how we manage deployment configuration itself is even harder and will take time. But the incentives to change will only grow. Software is being created at an ever greater pace, thanks to AI.

A vibe coded app that is not deployed is like a tree falling in the forest when nobody’s around. Did it make a sound?

Turning all the new AI goodness into value means more software deployments, with more churn, but with all the same concerns: stability, security, privacy, compliance, customer experience, etc.

Our current software configuration practices will be feeling the pressure.

Learn more

ConfigHub is still early days. We welcome you to try our free preview environment and we would love to talk to you on Discord. You can also email us at hello@confighub.com with your thoughts.