AEM as a Cloud Service
14 – AEM as a Cloud Service
Target: 3–4 years experienced AEM Developer Syllabus point covered (23): "If you have worked on AEM Cloud, what is the benefit? How is it better than on-premise?" Project domain: a global energy technology company's marketing site.
Before we start — the trap in this question
Your syllabus point 23 asks "what's the benefit, how is it better than on-prem." That phrasing invites a sales pitch, and a sales pitch is exactly the wrong answer.
Here's why. The interviewer almost certainly works on a project that either runs Cloud Service, is migrating to it, or deliberately stayed on 6.5. In all three cases they know the real trade-offs. A candidate who recites "auto-scaling, always up to date, lower TCO" sounds like they read the marketing page. A candidate who says "the biggest practical change for me was that /apps became read-only, which meant we had to rewrite five services that used admin sessions" sounds like they lived it.
So the answer that scores is the one framed around what actually changed for a developer — and that includes the things that got harder, not just easier.
There is also a second reason to be careful. This question is frequently a screening question for whether you've genuinely worked on Cloud Service. The follow-ups get specific fast: how do you get logs? what's an RDE? what happens to /apps at runtime? how do you create a service user? Vague benefit-talk followed by "I'm not sure" on those is worse than a smaller, honest claim.
Everything in this file has already appeared in earlier files — immutability in file 01, Repoinit in files 01 and 13, Asset Compute in file 09, pod recycling in file 10. This file assembles it into one answer.
1. Introduction
1.1 The one sentence that frames everything
On AEM 6.5 you own a server. On Cloud Service you consume a service.
Almost every difference follows from that.
A server is a machine you can log into. You can change it, restart it, put a file on its disk and expect it there tomorrow. You are also responsible for it — patching, upgrading, monitoring, backing up.
A service is something Adobe runs. The machines are containers created and destroyed as needed. They are immutable — you cannot change them while they run — and disposable — one might vanish and be replaced at any moment. You are not responsible for them, and you also cannot fix them.
That trade is the honest summary: you give up control and gain not having to care.
1.2 A real project example to adapt
"We're on Cloud Service, migrated from 6.5 about two years ago. The genuine day-to-day benefits are that we stopped doing version upgrades entirely — Adobe ships updates continuously — and the publish tier scales itself during campaigns, which used to mean provisioning instances weeks ahead and then paying for them all year.
The bigger change for us as developers was the discipline it forced.
/appsis read-only at runtime, so there's no hotfixing in CRXDE — everything goes through Git and a Cloud Manager pipeline with quality gates. That's slower for a genuine emergency, but it eliminated a whole class of problem where production had drifted from what was in source control.The migration itself was mostly about removing things Cloud Service doesn't allow — admin sessions, install hooks, a custom run mode, and a service that wrote generated files to local disk."
That covers benefits, the developer-facing change, an honest cost, and migration reality — four follow-ups pre-empted.
2. Core Concepts
2.1 The architecture, and what's genuinely different
From file 01, but focused on what changed:
graph TD CM["Cloud Manager<br/>the ONLY way in"] --> AU["Author service<br/>clustered · DocumentNodeStore / Mongo"] CM --> PU["Publish service<br/>AUTO-SCALING pods · SegmentNodeStore"] AU -->|"Sling Content Distribution<br/>pub/sub"| PU AU --> PV["Preview service"] CDN["Adobe-managed CDN"] --> DP["Dispatcher<br/>a container IN each publish pod"] DP --> PU AC["Asset Compute microservices<br/>processing OFF-instance"] --> AU
Four structural changes worth naming:
Publish auto-scales. Pods are added and removed based on traffic. That's the headline benefit, and it's also the source of the cluster problems in file 10 — you cannot know how many instances are running.
Content distribution replaced replication agents. On 6.5 the author pushed to a known list of publish instances. That can't work when pods appear and disappear, so Sling Content Distribution uses a pub/sub pipeline that pods subscribe to. A newly created pod pulls current content by itself. Full detail in file 18.
The dispatcher moved into the publish pod as a sidecar container, and its configuration lives in Git and is validated by the pipeline — rather than being hand-edited on an Apache box.
Asset processing moved off-instance to Asset Compute microservices, configured by Processing Profiles rather than the DAM Update Asset workflow (file 09).
The node store detail that catches people out, and which is worth getting right because it's a common near-miss:
Author uses the DocumentNodeStore backed by MongoDB, because the author tier is clustered and instances share one repository. Publish uses the SegmentNodeStore, because each pod holds its own read-only copy and speed matters more than sharing.
Most candidates say "the cloud uses Mongo" for both. Getting the split right is a genuine differentiator.
2.2 The genuine benefits — and how to argue each one
Not a list. Each one with the reason it actually matters.
No more version upgrades
On 6.5, an AEM upgrade was a project — weeks of regression testing, a migration window, and often deferred so long that you ended up several versions behind and the eventual jump was worse.
On Cloud Service, Adobe ships updates continuously with no downtime. The version problem simply stops existing.
Why this is the strongest benefit to lead with: it removes recurring project cost, not just operational cost. Teams on 6.5 spend real engineering time on upgrades that produces no features.
Auto-scaling publish
On 6.5, capacity was provisioned for peak. So you sized for the campaign, then paid for that capacity for the other eleven months.
A concrete framing: our campaign traffic is roughly ten times a normal day. On 6.5 that meant provisioning ahead and running the capacity year-round. On Cloud Service the publish tier scales during the campaign and back afterwards.
Deployment discipline
This one is a benefit and a constraint, which is why it's worth being honest about.
Cloud Manager pipelines are the only route to production. Every change goes through build, code quality gates, security testing, and functional tests on stage before reaching production.
The benefit: production cannot drift from source control. On 6.5, someone fixing something urgently in CRXDE at 2am creates a difference between what's running and what's in Git — and nobody discovers it until the next deployment overwrites the fix.
The cost: there is no emergency hotfix path. A genuine production emergency waits for a pipeline. That's a real trade and pretending otherwise is what makes an answer sound rehearsed.
Operational work disappears
Repository maintenance — compaction, revision garbage collection, data store garbage collection, index management — is real, ongoing work on 6.5. It's also invisible until it isn't: the classic 6.5 incident is a disk filling because compaction hasn't run.
Adobe handles all of it, along with monitoring, patching and backups.
Asset processing off-instance
On 6.5, DAM Update Asset ran on the AEM instance. Uploading a few thousand product images meant CPU-heavy image processing competing with authors, and authors noticing.
Asset Compute runs it externally. Authors stop being affected by asset ingestion, which is a benefit people don't anticipate until they've experienced the alternative.
A CDN is included
Adobe provides and manages a CDN. On 6.5 you brought your own — another contract, another configuration, another thing to coordinate.
2.3 What changes for a developer — the part that scores
This is the section that separates a real answer from a recited one. Six things change, and they're all consequences of immutability and disposability.
1. /apps and /libs are read-only at runtime
They're baked into the container image at build time. So:
- No hotfixing in CRXDE on production. Not restricted — impossible.
- CRXDE Lite is only available on development environments, not stage or production.
- No install hook can write to
/apps.
2. Service users and ACLs must come from Repoinit
There's no admin session, and install hooks can't create them. So everything structural — service users, ACLs, folder paths — is declared in Repoinit (files 01 and 13).
And this is the honest reframing: it's a constraint that turned out to be an improvement. Permissions now live in Git, get reviewed like code, and are identical across environments — instead of being clicked in per environment and drifting.
3. The Maven project must cleanly separate mutable from immutable
ui.apps holds immutable content; ui.content and ui.config hold mutable. Mix them and the build fails validation — it's enforced, not advisory.
4. Custom run modes don't exist
You get author and publish crossed with dev, stage and prod. No config.uat. Teams migrating from on-premise frequently had custom run modes and have to collapse them.
5. Local disk is scratch space
Pods are replaced during deployment, scaling, and health events. Anything written to local disk may vanish. It belongs in the repository or an external store.
6. Long-running processes are discouraged
Because pods recycle. A workflow paused on a human step survives fine — it's persisted. A step doing hours of continuous computation may not (file 09).
The interview answer for this section:
"The biggest change is that
/appsand/libsare immutable at runtime — baked into the container image. So there's no hotfixing in CRXDE, and CRXDE Lite isn't even available on stage or production.That has knock-on effects. Service users and ACLs have to be declared in Repoinit, because there's no admin session and no install hooks. The Maven project has to cleanly separate
ui.appsfromui.contentandui.config, and the build fails validation if you mix them. Custom run modes are gone — you get author and publish crossed with dev, stage and prod. And because pods are recycled, local disk is scratch space and long-running processes are discouraged.The honest framing is that most of those are constraints that turned out to be improvements. Repoinit meant permissions moved into Git and stopped drifting between environments. The package separation forced us to be clear about what's code and what's content. The one genuine cost is that there's no emergency hotfix path — a real production incident waits for a pipeline."
2.4 The honest limitations
Raising these unprompted is what makes the whole answer credible.
No emergency hotfix. Everything through a pipeline. For a genuine production incident that's a real constraint, and the mitigation is feature flags and configuration you can change through the faster config pipeline rather than a full build.
Less introspection. No CRXDE on stage or production, no Felix console for editing configuration. You get the Developer Console and downloadable logs, which is less than being on the box.
Constrained customisation. No custom run modes, no writing to /apps, no admin sessions, no assuming local disk. Things that worked on 6.5 sometimes have no direct equivalent.
Adobe's release cadence is yours. Continuous updates mean you don't control when the platform changes. That's mostly good, and occasionally you're debugging something that changed underneath you.
Migration isn't free. The Best Practices Analyzer typically finds real work — admin sessions, install hooks, custom run modes, local disk writes, custom asset workflows.
Cost is different, not automatically lower. Whether it's cheaper depends on the workload. The honest claim is that operational effort drops substantially; the licensing conversation is separate.
2.5 The tooling you should be able to name
Naming these is a quick check on whether you've actually worked on Cloud Service.
RDE is the one worth understanding, because it answers an obvious objection.
The problem it solves: a full Cloud Manager pipeline takes a long time. During active development, waiting that long to see a change on a cloud environment is unworkable.
RDE lets you deploy a bundle or content package to a cloud environment in seconds, using the aio CLI. It's for development iteration only — not a path to production — but it makes cloud development practical.
Mentioning RDE unprompted is a strong signal, because it's the thing you only know about if you've hit the problem it solves.
2.6 Cloud Manager pipelines
Types worth distinguishing:
Why several types exist: a dispatcher rule change shouldn't require a full application build and test cycle. Knowing that web-tier and config pipelines exist — and that they're the answer to "how do you change a dispatcher rule quickly" — is a practical detail.
Quality gates in a full-stack pipeline: code quality via SonarQube plus Adobe's own OakPAL rules, security testing, and functional tests on stage. Some findings are warnings; critical ones block the deployment.
The deployment itself is a rolling update — old pods keep serving until new ones are healthy, so the publish tier has no downtime.
2.7 Migration — the honest version
If asked how you'd migrate, the tools in order:
- Best Practices Analyzer on 6.5 — what will break
- Cloud Acceleration Manager — track the plan
- Repository Modernizer — restructure the Maven project
- Dispatcher Converter — convert dispatcher config
- Asset Workflow Migration — DAM workflows to Processing Profiles
- Content Transfer Tool — move content, then Content Copy for deltas
What actually breaks, which is the more useful half of the answer:
3. Internal Working
3.1 What happens during a deployment
graph TD A["Push to the Cloud Manager Git repo"] --> B["BUILD — Maven"] B --> C["CODE QUALITY<br/>SonarQube + OakPAL"] C -->|"critical findings"| X["BLOCKED"] C --> D["SECURITY TESTING"] D --> E["Build container images"] E --> F["Deploy to STAGE"] F --> G["Functional / UI tests"] G -->|fail| X G --> H["Deploy to PRODUCTION<br/>ROLLING update"] H --> I["Old pods drain,<br/>new pods take traffic"]
Three things worth drawing out:
The gates are real. Critical findings block. That's the discipline benefit, and it's also why there's no emergency path.
Images are built, not patched. A deployment produces new container images — which is exactly why /apps is immutable at runtime.
Rolling update means no publish downtime, but it also means components deactivate and reactivate on every deployment. Which is why @Deactivate matters more here than on a server you restart occasionally (file 06).
3.2 Why pods being disposable changes your code
graph TD A["A pod can vanish at any moment<br/>deployment · scaling · health event"] --> B["Local disk is SCRATCH"] A --> C["In-memory state is LOST"] A --> D["Long-running work may be INTERRUPTED"] A --> E["A scheduler runs on EVERY pod<br/>and the count VARIES"] B --> F["Repository or external store"] C --> F D --> G["Sling Jobs — persisted and retried"] E --> H["scheduler.runOn, or keep it on author"]
That single fact — pods are disposable — generates most of file 10's content. A scheduler running on an unpredictable number of pods, jobs needing persistence, and idempotency mattering because work gets retried, all come from here.
8. Comparison Tables
8.1 The full comparison
8.2 Pipeline types
8.3 What breaks in migration
8.4 The migration tools
9. Common Mistakes
10. Best Practices
On the answer itself. Frame around developer experience, not features. Volunteer the downsides. Have one concrete migration story ready, because that's what proves you were there.
On code. No admin sessions. Everything structural in Repoinit. Clean package separation. Never assume local disk or in-memory state survives. @Deactivate releases everything, because pods recycle constantly.
On background work. Scheduled work on author. Sling Jobs for anything substantial. Idempotent consumers, because work gets retried.
On operations. Feature-flag anything risky, so it can be disabled without a full build. Components should degrade rather than throw. Log well, because you can't get onto the box.
On migration. Best Practices Analyzer first. Start service users from zero permissions and widen on failure. Content transfer is usually the long pole.
11. Debugging on Cloud Service
What you have:
What you don't have: SSH, files on the box, editing OSGi configs in the Felix console on stage or production, and CRXDE on anything above dev.
What that changes about how you work:
Logging discipline matters more. You can't attach a debugger to production, so what you logged is what you get. That pushes you toward logging decisions and state transitions rather than only errors.
Health checks matter more. A silent failure — a scheduler that stopped, a service that's unsatisfied — is harder to notice without console access. Section 11 of file 10 makes the same point, and it's more true here.
RDE is how you iterate. A full pipeline is too slow for development, and RDE closes that gap.
And the honest framing: "It's less introspection than being on the box, and I'd rather have both. The mitigation is being more deliberate about logging and health checks — which is better practice anyway, but it was forced rather than chosen."
Next topic
15-Content-Fragments — your syllabus points 24 and 25: what a Content Fragment is, how models work, how you read one in a Sling Model, and the headless delivery story with GraphQL.
Topic 14 of the AEM Interview Preparation repository. Teaching style, energy-sector project domain.