Your content pipeline is lying to you, and in regulated software, that's a serious problem
<p>There is a category of bug that does not show up in your test suite, does not trigger an alert, and does not produce a stack trace. It looks like this: the wrong version of your content is running in production, and you have no reliable way to prove otherwise.</p> <p>For most applications, this is embarrassing. For software in regulated industries (medical devices, industrial systems, certified training applications, etc.) it can be a compliance failure with real consequences.</p> <p>This post is about why this happens, why the obvious fixes do not actually fix it, and what a correct architecture looks like.</p> <h2> The problem with treating content like database state </h2> <p>Most content pipelines work roughly like this: content lives somewhere editable (a CMS, a database, Notion, a
There is a category of bug that does not show up in your test suite, does not trigger an alert, and does not produce a stack trace. It looks like this: the wrong version of your content is running in production, and you have no reliable way to prove otherwise.
For most applications, this is embarrassing. For software in regulated industries (medical devices, industrial systems, certified training applications, etc.) it can be a compliance failure with real consequences.
This post is about why this happens, why the obvious fixes do not actually fix it, and what a correct architecture looks like.
The problem with treating content like database state
Most content pipelines work roughly like this: content lives somewhere editable (a CMS, a database, Notion, a spreadsheet), a build process or runtime query pulls it out, and the application delivers it to users.
The fundamental assumption baked into this model is that "current content" means "whatever is in the database right now." That assumption is fine for a marketing website where you want changes to go live immediately. It is quietly disastrous for applications where what was delivered to a user needs to be auditable, reproducible, and tied to a specific approval event.
Consider a company building certified training software for medical device manufacturers. Their content — the training material that end users complete to be certified on a device — must reflect what was reviewed and approved by the manufacturer. If an editor makes a change in the CMS, saves it, and that change goes live immediately in the training application, you have a pipeline where:
-
There is no reliable record of what content was actually delivered to a specific user session
-
An approved state can be silently overwritten by any subsequent edit
-
Future content revisions for the next operating procedure version cannot be safely developed without risk of contaminating current production content
-
An audit asking "what exactly did this user see on this date?" cannot be answered with certainty
None of these are edge cases in regulated software. They are exactly the questions that certification and compliance processes ask.
Why the obvious solutions fall short
"We'll just add an approval workflow to our CMS."
While restricting the publication of content can solve the immediate issue of controlling which content reaches production, it cannot prevent that future content revisions overwrite existing published content. This makes it impossible to operate multiple exactly defined revisions in parallel, as end-users gradually switch to new procedures at their own pace.
"We'll use database snapshots or backups."
Snapshots are a disaster recovery mechanism, not an audit trail. They are coarse-grained, difficult to query selectively, and not designed to answer "show me exactly what field X contained for entry Y at timestamp T and who approved it."
"We'll version our database records."
You can build this. It requires significant custom engineering, and you will need to think carefully about referential integrity across versions, query complexity for fetching a consistent snapshot of related content at a given version, and how to expose this to non-technical content editors in a way that does not cause confusion. Going down this path is a surefire way of spending development effort on closing down a never-ending series of edge-cases, where that effort could have been spent on further building out your core product instead.
"We'll bake content into the application binary at build time."
This solves the "content changed at runtime" problem but introduces a different one: the only way to update content is to rebuild and redeploy the entire application. Iteration speed becomes painful. More importantly, you still need a way to manage and audit what goes into the build — the source of truth upstream of the binary is still mutable.
What a correct architecture actually requires
The properties you need are specific and worth stating precisely:
Immutability by reference. A given version of your content, once approved, must be permanently retrievable by a stable identifier. Not "the current state of approved content" but "the exact state of content as of approval event #4471."
Referential consistency. If your content model has relationships (e.g. a training module references a set of questions, which reference a set of answer options) fetching a specific version must return a consistent snapshot of the entire graph, not a mix of versions from different points in time.
A separation between working state and production state. Authors need to be able to work on future revisions without those changes being visible to production consumers. This is a branching problem, not a permissions problem.
An audit trail that is structural, not appended. The history of what changed, when, and as a result of what approval event should be intrinsic to the storage model, not a log table bolted on afterward.
Git already solved this problem for code
If you step back, these are exactly the properties that Git provides for source code:
-
Every commit is content-addressed and permanently immutable
-
A commit captures a consistent snapshot of the entire tree at a point in time
-
Branches allow parallel workstreams without interference
-
The commit graph is a structural, tamper-evident audit trail
-
A specific historical state is always retrievable by commit hash or tag
The reason we do not instinctively apply this to content is partly historical (Git tooling was built for developers, not editors) and partly because the content model is usually relational in ways that flat files handle awkwardly.
But the core insight holds: if your content were stored in Git, you would get immutability, branching, and audit trail for free, because those are Git's foundational properties — not features you add on top.
Making this practical
The gap between "store content in Git" and "have a usable content pipeline" is real. A few things need to exist:
A schema that defines your content model formally. Ad hoc JSON or YAML files in a repository are not enough. You need a schema that defines types, relationships, and constraints, so that content can be validated and queried consistently.
An API layer that understands the content model. Content consumers (your application, your build pipeline) should not be parsing content files directly, as it would cause a lot of content-related code to build up in the consumer. Instead, consumers should be querying a typed API that resolves references, enforces the schema, and lets them specify which version of the content they want by ref (a branch name, a tag, or a specific commit hash).
A way to express approval in Git terms. The most natural model: content development happens on feature branches, a pull request represents the review and approval event, and merging to a production branch (or creating a tag) is the act of approving content for delivery. This is a well-understood workflow that countless engineering teams are already following.
An editing interface that shields complexity from non-technical editors. Authors should neither need to know what a commit is, nor have to worry about getting content to match the schema. They need a schema-conformant, form-based UI that saves their changes, and a clear way to submit content for review. The schema validation and Git operations happen underneath.
When this is in place, your application can query content by specifying a production tag or branch. What it receives is guaranteed to be exactly what was approved, not because of a runtime check, but because the storage model makes any other outcome structurally impossible.
The operational benefit beyond compliance
There is a practical benefit that has nothing to do with audits: you can safely develop next-version content in parallel with delivering current-version content to production, with zero risk of cross-contamination.
For the medical device training example: when a manufacturer releases a new revision of operating procedures, the training content for that revision can be developed, reviewed, and approved on a separate branch while the current certified training continues serving users unchanged. The two versions never interfere with each other. Switching production to the new version is a single operation (moving the tag or updating a ref) that is itself logged in the Git history.
This is not a compliance feature. It is just a sane way to manage content for software that has release cycles.
Where to go from here
If this problem pattern resonates with your context, the conceptual model I have described here is the foundation of Commitspark, a set of open-source tools I built that provides a GraphQL API over Git-backed, schema-defined content. It is one concrete implementation of these ideas, but the architectural principles apply regardless of what tooling you choose.
The more important takeaway is this: if your application delivers content that needs to be auditable, versioned, and approved — and you are currently managing that content in a mutable database or a CMS with no structural versioning — you have a gap worth closing before a compliance process asks you to close it for you.
Your feedback
If you previously encountered this problem of having to prove a specific version of content was in production, what were you building and how did you solve it?
Let me know in the comments.
Sign in to highlight and annotate this article

Conversation starters
Daily AI Digest
Get the top 5 AI stories delivered to your inbox every morning.
More about
modeltrainingreleaseGoogle AI educator training series expands digital skills push across K-12 and higher education - EdTech Innovation Hub
<a href="https://news.google.com/rss/articles/CBMie0FVX3lxTFBQTVFQNE91MHp2bEF1QlE5QlNLQ0daRjFHZVdzT09iOUpxNUZHbDEtWW9ybHdaYmFSbmUzbk1ReHBDS2FSZkpnMXVkeGQ4SEVMOG5WbnNNRUtvYjdiVDdJY1FUZ2pVTC05QUYxRkQwWUh5M1Z4aEpJLUtmcw?oc=5" target="_blank">Google AI educator training series expands digital skills push across K-12 and higher education</a> <font color="#6f6f6f">EdTech Innovation Hub</font>
Intelligence Dissolves Privacy
The future is going to be different from the present. Let's think about how. Specifically, our expectations about what's reasonable are downstream of our past experiences, and those experiences were downstream of our options (and the options other people in our society had). As those options change, so too our experiences, and our expectations of what's reasonable. I once thought it was reasonable to pick up the phone and call someone, and to pick up my phone when it rang; things have changed, and someone thinking about what's possible could have seen it coming. So let's try to see more things coming, and maybe that will give us the ability to choose what it will actually look like. I think lots of people's intuitions and expectations about "privacy" will be violated, as technology develop
Episode 2: I Was a Junior Developer and I Must Be Stopped
<p>Welcome back.</p> <p>Last episode, we reviewed a Laravel function that used three loops to reconstruct an array it already had, fired two database queries per item instead of one, and named a variable <code>$r_arr</code> with the confidence of a man who has never once been held accountable for anything.</p> <p>It was a good one, some of us liked it.</p> <p>So today, we are reviewing my hotel invoice generator. It is a PHP class called <code>ExcelController</code>. It imports guest data from an uploaded Excel file and exports a personalised invoice for each guest, packed into a zip file for download.</p> <p>It was never merged.</p> <p>The room numbers are completely random.</p> <p>My senior opened the PR. He read through it. He left seven comments. He never raised his voice. He never sen
Knowledge Map
Connected Articles — Knowledge Graph
This article is connected to other articles through shared AI topics and tags.
More in Products
Long Tail: Growth Investment Secured For AI-Driven Healthcare Utilization Platform - Pulse 2.0
<a href="https://news.google.com/rss/articles/CBMiowFBVV95cUxNa3lKZDhfaWlKVThYOFdKb2Fja2VpNzZyeVNqbXV0OERiN1FTc1RiaVVGd0lUWW0wdjQzVUNmU1NJU2tJSlJPUHl1Wjh4emZHXzRJRmh2LS1SdjRhOXZJa1hsMVFINFRBWHhyQUtRZzhya1hWTXpKZ3FvNkpZQmpLMmlvSjh0V0VKaU5pVE1TRWkyNTRqWWZaWFJtZ2s3VGNBRl9V0gGoAUFVX3lxTE1kY3RGWHZHRFRzTk1YczVtcmhpdVMwUlJSV3Vtb05IeHpPYWhQaEVLeVA5S2QzVk1qdWNPYU9wLVRuZjh5U2g2LWdvZHBaX29pNDcwYkdwd3pqY1p5N3F5QkV3NURMLURuNkpOOExRRkRIZ2RHUDVTaF9LTVVqckgtWWlIMWNubzRUVXlaSUtldlVWdDA5bXRHWFNWY1plQ3RIMlpVLVd2Qw?oc=5" target="_blank">Long Tail: Growth Investment Secured For AI-Driven Healthcare Utilization Platform</a> <font color="#6f6f6f">Pulse 2.0</font>
Israeli startups raise $1.2b as AI, cyber lead deals - Tech in Asia
<a href="https://news.google.com/rss/articles/CBMiigFBVV95cUxPd2FkUTV1SThoTDl3a0JTUG5ISDdsTzBuREoyanRwZHV6VzY0OS1jRXY5RXNBVHBWRmx5RlhNdlhCeFBiXzl4ek80LWZ5VzZWV19hX2NoOVVDYlJEWTV3NFIxSFQzRkFsaXFtd0dxM3YtN0J0UXlHSkx6WlM1YnhRdmR0QzRGSHhkcHc?oc=5" target="_blank">Israeli startups raise $1.2b as AI, cyber lead deals</a> <font color="#6f6f6f">Tech in Asia</font>
IBM FedRAMP AI Approval Puts Federal Growth And Valuation In Focus - simplywall.st
<a href="https://news.google.com/rss/articles/CBMi4AFBVV95cUxNaFB5ZTRKRmxvWEF2b2M4SVBjajlrY1JnT1BTNlQzcy1iTnFLTW1DSkdsWDNneVVMQ0hwVWhOd1JXNTl6MHhNNlgtdkQyWXBpeWlwMHg2R0xQNkpkRVBvWC1ta0J1VmNlV2ZDaXFBWlJuX2NIYWswSDJIUjYwb2JUblBtenVNcWJjaF9RZ2EwMW8xZ1F0QlRyeHhlZ3pQWXFnWXZHMHlYT2pVQk9haVZEYVBaOGI4Z3VPVVpTUFQwNFA3NjBJRmc0TnlpQkZLVWFHc3dkZVlGSmpJRUtPdzhKTdIB5gFBVV95cUxPT2NkQnp3MTZaVERhMEUwaWZkTklRengwQ0U0alBUaG00dWNiYXkwMDJUYWVSdEdUcldUbm1RNDVORGFrN21aNTdRMHdaUHoyZUM1OVg4aEdud3V2bm9nRXhPdXpPRDhzMWZlXzVwdU9zeVFqNmJsREhFcERtZmtMOW1ZdmlobHpCTjFINW1rWXE1ZEc5RkQ4ZmhhdW9EQ1FIYjBXek5lUmZVTHk1d0c4WERwMm5LeXZsNWhZaGJLQUhaNVViN09ISW5yRWpSWDhOMmo4S2tHRllCeFpNUVNUblNUWGZZUQ?oc=5" target="_blank">IBM FedRAMP AI Approval Puts Federal Growth And Valuation In Focus</a> <font color="#6f6f6f">simplywall.st</font>
IBM Stock Rises after Getting Government Approval for Its AI and Automation Tools - TipRanks
<a href="https://news.google.com/rss/articles/CBMisAFBVV95cUxPZGJtNW9XVU5tWXc5RzNJdmcyNXpLLS1aTmpXTDN6SUthX3JHNVZjTFJUakRjM1VNWXRwdFBmUmQ3Y0Z4SDdUYUpHcXpGLUxGWURkLTk5WDRGeVBkeFNwWWI5RE9UUzYySFRhelR0cHdFLURNQzBXRVBqUUJMeFJVb3pPWUNnb2o4UDAxWmhiUUdEdWRod3pkSlRHX0ZWbGNEQWVRbUhGb3gwVHhkSlp5bA?oc=5" target="_blank">IBM Stock Rises after Getting Government Approval for Its AI and Automation Tools</a> <font color="#6f6f6f">TipRanks</font>

Discussion
Sign in to join the discussion
No comments yet — be the first to share your thoughts!