AEM in 40 Days
CalendarPhase 2 · Environment & Project Anatomy

Day 11 of 40

Mutable vs Immutable Content

Why /apps is read-only at runtime and what filter.xml controls

~40 min read2 videos2 source pages

By the end of today you should be able to

  1. State precisely which repository paths are mutable and which are immutable
  2. Explain why the distinction exists and what it buys you operationally
  3. Use repoinit to create mutable structures such as service users and ACLs at startup
  4. Explain what the Repository Structure Package is for and why builds fail without it

The split

AEM as a Cloud Service divides the repository in two, and the line is absolute:

  • Immutable/apps and /libs. Written only at deployment time. Read-only at runtime, for everyone, including admin.
  • Mutable/content, /conf, /var, /home, /etc. Writable at runtime by authors, workflows and your code.

This is not a policy someone can relax. It is enforced by the runtime, and it is what makes Cloud Service's deployment model possible: because /apps can only change through a deployment, Adobe can build a new instance from the deployed artefact, run both versions side by side, and cut over — the blue/green rollout you get for free on every deploy.

The practical rule

If a human should be able to change it after go-live, it is mutable and belongs in /content or /conf. If only a deployment should change it, it is immutable and belongs in /apps.

Where things actually go

  • Component definitions, HTL, dialogs, clientlibs, template types/apps, from ui.apps.
  • OSGi configuration → /apps/<appId>/osgiconfig, from ui.config.
  • Editable templates and policies → /conf, from ui.content. Authors with the right permissions can edit these at runtime, which is the entire point of "editable".
  • Pages and assets → /content, owned by authors.

Note the asymmetry that trips people up: template types are immutable code, but the templates made from them are mutable configuration. That is deliberate — developers define what kinds of pages are possible, authors compose specific ones.

repoinit: creating mutable things at startup

Some mutable structures must exist before any author touches the system — a service user, a folder with specific ACLs, a base content path. You cannot ship those in ui.apps (wrong side of the line) and shipping them in ui.content would overwrite them on every deploy.

The answer is repoinit: a small declarative language, delivered as an OSGi configuration, executed at startup. It is idempotent, so running it repeatedly is safe:

create service user wknd-content-reader with path system/wknd

create path (sling:Folder) /content/wknd/settings

set ACL for wknd-content-reader
    allow jcr:read on /content/wknd
end

This is the supported way to create service users and ACLs on Cloud Service, and it is what day 31 builds on. Because it lives in ui.config, it is versioned in Git and deployed by the pipeline like everything else.

The Repository Structure Package

FileVault will not let a package define a filter for a path that no package in the build actually creates — it cannot know whether the parent exists. But your ui.apps and ui.content packages legitimately need to write into shared roots like /apps/wknd and /conf/wknd.

The Repository Structure Package solves this. It is an (almost empty) package whose only job is to declare the roots your other packages depend on. Sub-packages reference it via <repositoryStructurePackages> in their filevault-package-maven-plugin configuration, and the build then validates that every filter falls inside a declared root.

The error you will meet

A build failure saying a filter root is not covered by the repository structure package almost always means you added a new top-level path to a filter without declaring it. Add the root to the structure package and the build passes.

Today's takeaway

/apps changes only by deployment; everything a human edits lives elsewhere. Use repoinit for mutable structures that must exist at startup, and keep the repository structure package in sync with your filters.

Watch

Adobe's own videos for this topic. They load only when you press play.

Intro to Mutable:Immutable
Repository Structure

Read on Experience League

The primary sources these notes are drawn from.

Your notes

Saved automatically to this browser.

Check yourself

11 questions on today's material. 80% to pass.

Take the quiz