ADL vs SaaS Headless CMS
Contentful and Storyblok Interpret a Declaration You Don't Hold
TL;DR: Contentful and Storyblok are, in one sense, this series’ fifth proof: define a content model, and the platform interprets it into a working API — no generated code, globally delivered, at enterprise scale. But the SaaS headless CMS splits from ADL on two axes at once. First, the declaration lives in the vendor’s cloud: your domain model is data in someone else’s system, edited through their UI, its history a folder of migration scripts. Second, the model describes only content shapes, so every rule (validation past field basics, lifecycle past draft/publish, any real permission logic) smears across webhook handlers, serverless functions, and every app that consumes the content. ADL’s counterposition is one artifact: the whole domain, rules included, in a YAML file in your repo.
The steelman
Take the category seriously first, because it solved a genuinely hard problem.
Contentful is the enterprise answer to a real question: how does one body of content feed a website, three apps, a kiosk, and a partner integration without being rewritten for each? Model your content once (content types, fields, validations, references) and Contentful serves it through CDN-backed delivery APIs with the latency, localization machinery, preview environments, and SLAs that global content operations actually require. Storyblok attacks the same category with the best editorial trick in the business: a visual editor where editors click on a live preview of the page and edit the component under the cursor. Content is built from nestable components (bloks) so the model maps to how pages are actually composed, and non-technical editors work in something that feels like the site itself rather than a database form.
Both deserve the same architectural credit this series gave json-server, PostgREST, JDL, and Strapi: nobody generates code from a Contentful content type. The model is interpreted by the platform into APIs, live, on every request. The industry’s most polished content businesses run on declaration-executed-directly. That argument is over.
So the disagreement isn’t interpretation. It’s two other things: where the declaration lives, and how much it can say.
Where the declaration lives
An ADL domain is a file. It sits in your repository; it diffs; it gets reviewed in a pull request; it can be printed, audited, and handed to a new engineer as the definition of the system. When this series talks about reviewing a backend in an afternoon, that’s the artifact being reviewed.
A Contentful or Storyblok model is data in the vendor’s system. It was built by clicking in a web UI, it lives behind their management API, and its evolution is recorded (if you’re disciplined) as a folder of migration scripts: imperative JavaScript that mutates the model step by step. Export tooling exists, and serious teams script their models rather than clicking. But notice what the discipline is reconstructing: a reviewable, versioned declaration — the thing ADL simply is. The best practice for operating a SaaS content model at scale is an effortful approximation of a YAML file in git.
This isn’t a gotcha; it’s a sovereignty statement. Your content sits in their database, your model in their config, your uptime on their status page. For content, that trade is often correct (see the concessions). The trap is promotion: the model builder feels like a schema designer, so teams start putting application data behind it (orders, applications, records with lifecycles and rules) and wake up with their system of record defined in a vendor’s UI, mutated by scripts, and governed by an editorial permissions model that was never meant to say who may approve a grant.
How much it can say
Because these are content platforms, the model’s vocabulary is content-shaped, and the fence appears exactly where it did in the last three essays:
Lifecycle. Draft, published, scheduled: the publishing machine, again, hard-coded. Editorial workflow features on premium tiers add review steps for editors in the CMS. A domain lifecycle (submitted → under_review → approved, role-guarded, with required fields per transition and effects on entry) is not expressible. It gets built in the consuming application, or in webhook-triggered functions, or both, and nothing in the platform stops a management-API write from teleporting the status field.
Validation. Field-level rules exist and are decent: required, patterns, ranges, allowed values. Cross-field and cross-record rules (“a published article requires an excerpt,” “the reviewer may not be the author”) do not. And here the SaaS shape makes the smear strictly worse than Strapi’s: enforcement happens at entry, in the editor UI, so any rule the model can’t express is enforced by editor discipline plus re-implementation in every app that writes through the management API. Three consumers, three copies of the rule, or fewer copies than consumers.
Permissions. Roles govern editorial actions: who edits, who publishes, per space or content type. Field-level and expression-conditional domain permissions (“the owner and HR read salary; only HR writes it”) are outside the model. They land in your API layer — the one the headless CMS was supposed to save you from writing.
Everything derived or reactive. Computed values, aggregations, side effects: webhooks firing at your serverless functions, with your retry logic, in your fourth codebase.
Sum it the way an auditor would. Ask “what are the rules of this system?” and the answer is: the model config in the vendor’s cloud, plus the migration script folder, plus the webhook handlers, plus the validation sprinkled through every consuming frontend. The declaration didn’t fail: it declared shapes, delivered them globally, and left the rules to diaspora. ADL’s position is unchanged from Part 13: the rules are the domain, so they belong in the declaration — and a CMS worth of content types, editorial roles, validation, and the publishing machine itself fits in one declared file (the seeds include exactly that).
The honest concessions
Global content delivery is solved, and not by us. CDN-edge APIs, image pipelines, localization at scale, preview environments, five-nines aspirations with someone else’s pager attached. Kalos is a runtime you operate; its job is to be the system of record, not a CDN. A content operation shipping one body of content to many surfaces worldwide is these platforms’ home game, and they win it.
The editorial experience is real product. Storyblok’s visual editor in particular is the kind of thing editors choose employers over. Kalos renders nothing. A UI against its APIs and schema endpoint is yours to build. If daily editorial UX is the buying criterion, this comparison ends before it starts, in their favor.
Zero ops is worth money. No server, no upgrades, no security patching at 2 a.m. Self-hosting a runtime is a real cost ADL asks you to carry in exchange for sovereignty. Both sides of that trade are legitimate; only pretending there’s no trade is not.
Closer
The SaaS headless CMS proved the model could live outside the code; ADL asks why it should live outside your repo.