By treating fully rendered Kubernetes configuration as queryable data, platform engineering teams can achieve fleet-wide visibility and automate compliance without complex scripting.
In my previous articles, I showed several Config-as-Data example apps built on ConfigHub, from a fleet cost estimator to a CVE scanner. They all rely on one capability: querying your configuration as data.
Also, in a previous exploration of how Helm charts meet Configuration as Data, we examined how rendering Helm outputs directly into ConfigHub transforms configuration into a first-class data asset. The natural follow-up question for platform engineers is: Once configuration is stored in a database, what is the practical operational value?
The short answer is same, an ability to query.
This article explores --where-data, a ConfigHub feature designed by our CTO Brian Grant, that enables teams to query inside their configuration. Rather than filtering on external metadata, --where-data lets you interrogate the actual fields of the Kubernetes manifests you intend to deploy. It provides a direct solution to the “Visibility Gap” previously discussed in my Variants architecture breakdown.
The Visibility Gap in GitOps Stacks
When tasked with finding missing resource requests across a fleet, engineers typically attempt two approaches, both of which fall short:
1. Grepping the Git Repository
The specific values you are looking for often do not exist in Git. They emerge only after rendering — after Helm substitutes variables, Kustomize applies patches, and CI pipelines stitch overlays together. Running grep -r "cpu:" . across a repository yields template placeholders, not deployed reality. You are searching the recipe, not the final state.
2. Querying Live Cluster State
Put Git repos aside, you could use kubectl or runtime auditing tools to retrieve live state. But they typically operate on a per-cluster, per-context basis. More importantly, live state dictates what is running now, not what is declared as intended state. Running fleet-wide audits via Kubernetes APIs usually requires writing custom scripts to loop through dozens of kubeconfig files and merge JSON outputs manually.
Both approaches fail for the same underlying reason: in traditional GitOps pipelines, fully rendered configuration only exists ephemerally inside CI on its way to a cluster. You cannot easily query what doesn’t sit still.
ConfigHub’s architecture resolves this by making rendered configuration persistent. Every “Unit” (a deployable configuration package) stores literal, fully materialized configuration in a database. And data in a database can be queried at scale.
Fleet-Wide Queries in a Single Command
If you remember my Cost Estimator app, here is a similar example on how the cost-review question is answered in ConfigHub.
# Identify every unit, in every space, where a container sets a CPU request
cub unit list --space "*" \
--resource-type apps/v1/Deployment \
--where-data "spec.template.spec.containers.*.resources.requests.|cpu != ''"
Three mechanisms are at work in this single command:
-
--space "*": Executes the query across the entire accessible fleet—dev, staging, production, across all regions. -
--resource-type apps/v1/Deployment: Narrows the scan strictly to workloads containing pod templates, filtering out irrelevant objects like ConfigMaps or Secrets. -
--where-data: Acts as the predicate, evaluated directly against the stored JSON/YAML payload of each unit.
The path expression follows the YAML structure: it descends to containers, fans out over every array element using *, and checks resources.requests.cpu.
The seemingly odd .| syntax in the path above is not a typo. It is the split-path operator, an essential feature for running accurate compliance queries against real-world fleets.
The | character divides the path logically: everything to the left must exist for a resource to be considered, while everything to the right is allowed to be absent. Missing fields do not cause the match to fail; they actively participate in it.
This difference is important. A cost review doesn’t look for workloads that have CPU requests; it looks for the ones that do not:
# Identify every Deployment where a container has NO CPU request,
# including containers missing the 'resources' block entirely.
cub unit list --space "*" \
--resource-type apps/v1/Deployment \
--where-data "spec.template.spec.containers.*.|resources.requests.cpu = ''"
By moving the split earlier in the path (... containers.*.|resources), the entire resources subtree becomes optional. If a container lacks a resources block entirely, it still evaluates to a match, which is precisely the workload you are hunting.
Without this absence-tolerant matching, a naive JSONPath query would silently drop containers missing the field, leading to false-positive “green” compliance reports simply because the worst offenders failed to resolve in the query.
This same logic applies natively to security audits:
# Identify template spec missing runAsNonRoot, including those with no securityContext
--where-data "spec.template.spec.|securityContext.runAsNonRoot != true"
Unifying Metadata and Content Data Queries
ConfigHub allows platform engineers to use --where-data (content data filtering) in conjunction with --where (metadata filtering—such as labels, gates, or timestamps). These also can be combined into a single clause using the Data. prefix:
# Find 'Backend' units whose deployments run more than one replica
cub unit list \
--space "*" \
--where "Labels.Tier = 'Backend' AND Data.spec.replicas > 1"
ConfigHub handles this combination seamlessly. You do not need to worry about the difference between querying metadata and querying configuration content; you simply ask the question, and the platform delivers the unified results.
From Visibility to Action: Bulk Configuration Mutation
Configuration as Data doesn’t just show you the fleet, it also lets you change it. It also does not make sense to make change one-by-one. In ConfigHub, the same predicate used to filter a list can be used to scope a bulk operation. (The below example is a bulk function invocation operation)
# Preview: apply a baseline resource request to every under-specified container
cub function set \
--space "*" \
--where-data "spec.template.spec.containers.*.|resources.requests.cpu = ''" \
--dry-run -o mutations \
set-container-resources
-- requests --cpu 100m --memory 128Mi
Running this with --dry-run -o mutations generates a precise, color-coded, per-unit diff detailing exactly what will change across the fleet. The entire workflow—query, select, preview, and mutate—operates on a single, unified predicate.
Applying automated, fleet-wide mutations naturally raises concerns about breaking production. This is where ConfigHub’s governance model steps in. Mutations generate new revisions, and revisions must pass predefined Apply Gates and approvals before they can touch a live cluster.
Furthermore, once a query proves its operational value, it can be saved as a Filter — a named, shareable entity that can drive UI Views or scope deployment Triggers.
Yesterday’s ad-hoc FinOps audit becomes today’s automated standing policy.
Summary
When we are saying “Configuration as Data”, it is frequently misunderstood as simply a storage debate (putting YAML in a database instead of Git). However, storage is just the prerequisite. The true value lies in what that storage unlocks: rendered configuration that remains persistent long enough to be interrogated and acted upon.
Features like --where-data convert multi-day compliance scripting tasks involving dozens of kubeconfigs into a single CLI command, handling edge cases like missing fields natively, and keeping the remediation just one --dry-run away.
Key usages
-
Query the fields, not just metadata.
--where-datamatches against the rendered YAML itself — walk the path (spec.template.spec.containers), fan out over array elements with*, and test a field likeresources.requests.cpu. -
Use the split-path
|to catch what’s missing. Everything left of|must exist; everything right is allowed to be absent. So Pod template'scontainers.*.|resources.requests.cpu = ''finds containers with no CPU request at all — the offenders a plain path would silently skip. -
Scope it across the whole fleet. Pair it with
--space '*'and--resource-type apps/v1/Deploymentto run one predicate over every environment at once, and blend in metadata with theDataprefix--where '... AND Data.spec.replicas > 1'. -
Turn the query into the fix. The same clause scopes a bulk mutation —
cub function set set-container-resources --where-data '...' --dry-run -o mutationspreviews exactly what changes everywhere it applies, before anything is released.
