Requirements
- Tenants (stacks) with content types, entries, assets, locales with fallback, environments (dev/staging/prod).
- Branches: fork the content model and content, work in isolation, compare and merge back.
- Releases: bundle entries and assets across locales and deploy them atomically to an environment, now or on a schedule.
- Enterprise scale: large tenants, big bulk operations, strict RBAC.
High-level design
Deep dive 1 — Branches
- Creation: copy-on-create or copy-on-write for the content model and entries. Let the caller choose which environments to clone: omitted means all,
[]means none, and a list means only those. Resolve and validate at the API layer so bad input fails early. - Compare and merge: diff by UID per item (added / modified / deleted). Merge strategies decide conflicts. Global-field changes affect every content type that embeds them.
- Merge as a job: large merges run asynchronously. The job API should expose a per-item breakdown (item, change type, strategy applied, status, affected content types). Otherwise users export the whole branch just to see what changed.
Deep dive 2 — Releases and locale fallback
- If a locale isn't localised, entries fall back to the master locale's content. That's convenient, but it can publish content into a market that was never reviewed.
- A "Disable fallback publishing" rule has to be enforced server-side in the release service, not only in the UI, because API and CLI users bypass the UI.
- Choose failure semantics deliberately: synchronous add fails all-or-none and lists offending items; bulk add skips invalid items and adds the rest; a deploy-time check skips items that became invalid after they were added.
- Reuse the existing status (
SKIPPED) and error envelope to keep clients compatible. Leave legacy v1 behaviour unchanged.
Deep dive 3 — Scale and tenancy
- Every query is tenant- and branch-scoped by construction (repository layer), with compound indexes that start with
{stack, branch, …}. - Bulk operations are chunked, resumable and idempotent, with per-tenant concurrency caps so one tenant can't starve others.
- Publishing emits events for webhooks, search indexing and CDN purge (see Event-Driven Architecture).
I was tech lead on branch-creation environment cloning, branch merge job item details, and cross-locale release items / Disable Fallback Publishing, and I owned platform architecture for Taxonomy RBAC, Variants and Branches Env. See the case studies for the full decision write-ups.
Sources & further learning
Videos, courses, docs and books I recommend for this topic.
Related topics
Multi-Tenant SaaS Architecture
Serve many customers from shared infrastructure while guaranteeing isolation of data, performance and configuration per tenant.
Event-Driven Architecture
Services announce facts ("EntryPublished") and others react asynchronously — decoupling producers from consumers in time, space and knowledge.
Idempotency
Doing an operation twice has the same effect as doing it once. The foundation of safe retries, at-least-once messaging and reliable APIs.
API Evolution & Backward Compatibility
Change APIs without breaking clients — additive changes, tolerant readers, versioning strategy and explicit compatibility boundaries.
Saga Pattern
Keep data consistent across services without distributed transactions — a sequence of local transactions, each with a compensating action if a later step fails.