Config as data

One record per client as the single source of truth for your platform, so adding a client is a data change rather than a code change.

By: Benjamin Clark

Intent

This pattern assumes a platform that manages many entities of the same kind, such as clients, sites or products, each configured differently. It makes one record per entity the single source of truth for that entity's configuration. Services read the record through a typed model that enforces its rules, infrastructure is generated from it, as in data-driven Terraform, and it changes only through an API that validates and audits every change. This enables three outcomes:

  1. Adding an entity, or changing how one is set up, is a data change rather than a code change.
  2. Services can't disagree about an entity, and its infrastructure can't drift from its record, because all of them derive from the same source.
  3. People outside engineering, such as the operators who onboard clients, can change configuration safely, with every change validated and recorded.

Motivation

Without a single source of truth, each entity's configuration ends up spread across code, environment settings and separate systems. That fails in three ways:

  1. Adding an entity is slow and error-prone. Each new one needs changes in several repositories, and every change is another chance to miss a step.
  2. Nobody can say with certainty how a given entity is set up. Its configuration is kept in several places that overlap, and they drift apart into a split-brain, with no copy you can trust over the others.
  3. Engineers become a bottleneck. When every change to configuration is a change to code, each one waits on an engineer, however small it is.

This pattern gives every entity one place to look and one place to change. The API is the only way to write a record, and it validates each change against the same typed model that services read through, so anything a service loads can be trusted. Each record carries the full set of feature flags, checked against a registry of the flags that exist, so a mistyped flag is rejected when it's written rather than discovered in production. Each change is saved together with the events it triggers, as in a transactional outbox, so every change reaches the immutable audit trail, and a new entity's infrastructure is requested straight away, as in automatic client provisioning.

Applicability

Use this pattern when:

  1. A platform manages many entities of the same kind, such as clients, sites or products, each configured differently.
  2. People outside engineering need to change that configuration without waiting on a code change.
  3. Several services, and the infrastructure, depend on the same configuration.

Do not use this pattern when:

  1. There are a handful of entities that rarely change, where configuration in a reviewed repository is simpler.
  2. The settings change per user or per request. Those belong in the application's own data, not in the platform's configuration.

Structure

Sequence diagram of the Config as data pattern, whose participants are listed below

Participants

ParticipantRole
AdministratorCreates and updates entities through the API, with no code change.
Admin APIThe only way to write a record. It validates each change through the typed model, saves it with the events it triggers, and relays those events.
Feature registryLists the feature flags that exist, so a write can reject one that doesn't.
Entity tableHolds one record per entity, keyed on a reference that never changes, because infrastructure is named after it. It can be kept in any database that suits, such as a NoSQL database like Amazon DynamoDB.
Audit trailRecords every change, as in the immutable audit trail.
ServicesRead entities through the typed model rather than the raw record, so all of them see the same validated view.
Deploy workflowFetches the records, and generates each entity's infrastructure from them.

Constraints and trade-offs

  1. Configuration leaves pull request review. In a repository, every change is reviewed and versioned by default. In a table, the API's validation and the audit trail have to provide that instead, and neither puts a second person in front of a change before it takes effect.
  2. Every service and the infrastructure read the same record, so changing its shape is a contract change that each of them has to take up.
  3. Side effects follow the change rather than happen with it, so a new entity's infrastructure and its audit entry appear shortly after its record does.

Part of how I deliver

This is what lets a platform onboard its next client in minutes, rather than as a project. It's one of many patterns I bring through contract delivery, and the tables and flags take the shape of your own product.

Is every new client a project?

I build multi-tenant platforms where adding a client is routine, and each client's data stays its own. If you're building one, or yours has become hard to scale, book a call and we'll talk it through.

© 2026 Sudoblark Ltd. | Registered in England and Wales | Company number 14712154 | VAT number GB 438 1548 82 | Registered office: 1 Cedar Office Park, Cobham Road, Wimborne, BH21 7SB