Understanding Adobe Experience Manager Architecture
From Browser Request to HTML Response
If you've worked with React, Angular, Spring Boot, or ASP.NET, Adobe Experience Manager (AEM) can feel unfamiliar at first. Not because it's more complicated, but because it approaches web development from a completely different perspective. In this article, we'll build a high-level mental model of AEM and follow a browser request from start to finish, so you'll understand how all of its major pieces fit together.
Reading time: 8 min
Why AEM Feels Different
Most web applications follow a familiar pattern.
A request reaches a router, the router selects a controller, the controller calls one or more services, retrieves data, and finally returns a response.
If you've spent years building React applications backed by Node.js or Spring Boot, this flow probably feels natural.
AEM, however, asks a different question.
Instead of asking:
"Which controller should handle this request?"
it asks:
"Which content resource does this request represent, and which component should render it?"
That may sound like a small difference, but it's one of the core ideas behind AEM. Once you understand this shift—from controller-driven to resource-driven—the rest of the platform starts to make much more sense.
The Big Picture
Before we dive into individual technologies, let's look at the entire architecture from a high level.
At first glance, this may seem like a lot of moving parts.
Don't worry about understanding every box yet.
The goal of this article isn't to master each technology. It's to understand how they work together. Once you have that mental map, learning each individual topic becomes much easier.
A Typical Request
Imagine a visitor opens the following URL:
https://www.example.com/products/cloud-platform.html
To the user, it's just another webpage.
Behind the scenes, however, AEM processes that request through several layers before any HTML is returned.
At a high level, the request follows this path:
The browser sends the request.
Adobe's CDN checks whether a cached response already exists.
Dispatcher evaluates security rules and its cache.
If necessary, the request reaches an AEM Publish instance.
Apache Sling resolves the requested content.
A component is selected to render that content.
A Sling Model prepares the data.
An OSGi Service performs any reusable business logic.
HTL generates the final HTML.
The response is returned to the browser.
This lifecycle is the foundation of almost every AEM application, regardless of whether you're building a marketing website, an enterprise portal, or a headless content platform.
A High-Level Request Flow
Notice that AEM isn't always involved.
If the page has already been cached, the browser may receive a response without Publish rendering anything at all. That's one of the reasons enterprise AEM sites can handle large amounts of traffic efficiently.
The Core Building Blocks of AEM
Now that we've seen the overall flow, let's briefly introduce the technologies that make it possible.
Author
The Author environment is where content creators do their work.
This is where marketing teams, content authors, and designers create pages, edit text, upload assets, and preview changes before they become public.
Think of Author as the content management workspace.
Visitors never access this environment directly.
Publish
Once content is approved, it's published to one or more Publish instances.
Publish is optimized for one purpose:
Serving content to visitors as quickly and efficiently as possible.
Unlike Author, Publish doesn't include page editors or authoring tools. Its job is simply to render pages and respond to incoming requests.
A useful way to remember the difference is:
Author creates content.
Publish serves content.
Dispatcher
Before most requests reach Publish, they pass through Dispatcher.
Many developers think Dispatcher is just a cache.
Caching is certainly one of its most important responsibilities, but it's not the only one.
Dispatcher also acts as a security layer by filtering incoming requests and preventing unnecessary traffic from reaching AEM.
Whenever possible, it returns a cached page instead of asking Publish to render it again.
That reduces server load and dramatically improves performance.
Think of Dispatcher as the front door of your application.
Every visitor enters through it.
Apache Sling
If Dispatcher forwards a request to Publish, Apache Sling takes control.
Sling is the web framework behind AEM.
Instead of routing requests to controllers, Sling resolves them to content resources.
That resource-driven architecture is one of the defining characteristics of AEM.
It's also one of the biggest mindset shifts for developers coming from traditional MVC frameworks.
JCR
At the heart of AEM is the Java Content Repository (JCR).
Rather than storing content in relational database tables, AEM stores it as a hierarchy of nodes and properties.
Pages, components, assets, and configurations all live inside this repository.
When Sling resolves a request, it's ultimately reading content from the JCR.
You can think of the JCR as the content database for AEM.
Components
Everything you see on an AEM page is built from components.
A page isn't one large HTML file.
Instead, it's a collection of reusable building blocks.
Examples include:
Hero banners
Navigation
Cards
Carousels
Product lists
Footers
Each component is responsible for rendering one piece of the page.
This component-based architecture makes it possible to reuse the same functionality across hundreds or even thousands of pages.
Sling Models
Components often need more than raw authored content.
Maybe a date needs formatting.
Maybe a URL needs to be generated.
Maybe data has to come from another service.
That's where Sling Models come in.
A Sling Model prepares data before it's rendered.
Instead of filling HTL templates with Java logic, components receive clean, presentation-ready data.
@Model(adaptables = SlingHttpServletRequest.class)
public class HeroModel {
@ValueMapValue
private String title;
public String getTitle() {
return title;
}
}
One of the easiest ways to think about a Sling Model is as a view model. It sits between the repository and the HTML, transforming raw content into something that's easy for the template to display.
OSGi Services
Not every piece of logic belongs inside a component.
Suppose several components need to:
build product URLs,
call Azure Search,
communicate with Workfront,
validate business rules,
integrate with an external API.
Rather than duplicating that logic, AEM places it inside reusable OSGi Services.
These services can be shared across the application, making the codebase easier to maintain and test.
HTL
Once all the data has been prepared, HTL (HTML Template Language) generates the final HTML.
HTL is AEM's server-side templating language.
Its responsibility is intentionally simple:
Render HTML.
Business logic belongs in Sling Models and OSGi Services—not inside the template itself.
A simple example looks like this:
<sly data-sly-use.model="com.example.core.models.HeroModel" />
<h1>${model.title}</h1>
Notice how little logic appears in the template.
That's considered good HTL design.
Client Libraries
A modern website needs more than HTML.
It also needs CSS and JavaScript.
In AEM, these frontend assets are managed through Client Libraries, often called ClientLibs.
Instead of manually including dozens of files, components reference reusable Client Library categories.
This keeps frontend assets organized, reusable, and optimized for production deployments.
React Integration
Many enterprise AEM projects combine HTL with React.
HTL renders the initial HTML on the server, providing fast page loads and good SEO.
React is then used where rich client-side interactivity is needed, such as search experiences, dashboards, or AI-powered interfaces.
Rather than replacing AEM, React enhances it by adding rich client-side interactivity where it's needed, while AEM continues to manage content and server-side rendering.
Each technology focuses on what it does best.
How Everything Fits Together
If you only remember one diagram from this article, make it this one.
Every layer has a single responsibility.
That separation of concerns is one of the reasons AEM scales well for large enterprise projects and large development teams.
Architecture at a Glance
At this point, you've seen the major pieces of AEM and where they fit in the request lifecycle.
Before we finish, here's a quick reference you can use whenever you need to refresh your memory.
| Technology | Think of it as | Primary Responsibility |
|---|---|---|
| Author | Content workspace | Create and manage content |
| Publish | Public website | Serve content to visitors |
| Dispatcher | Security gate & cache | Protect and cache requests |
| Apache Sling | Request engine | Resolve resources and render components |
| JCR | Content repository | Store pages, assets, and configurations |
| Component | Building block | Render one part of a page |
| Sling Model | View model | Prepare data for rendering |
| OSGi Service | Shared business logic | Reusable application services |
| HTL | HTML template | Generate server-side HTML |
| Client Libraries | Frontend assets | Deliver CSS and JavaScript |
Five Things to Remember
If you forget everything else, remember these five ideas:
1. AEM is resource-driven
Unlike traditional MVC frameworks, AEM doesn't start by looking for a controller.
It starts by asking:
Which resource does this request represent?
2. Components are the foundation of every page
Pages aren't built as one large template.
They're assembled from reusable components that authors can place on a page.
This makes large enterprise websites much easier to maintain.
3. Every layer has one responsibility
AEM works well because responsibilities are separated.
Dispatcher handles security and caching.
Sling resolves requests.
Sling Models prepare data.
OSGi Services contain reusable business logic.
HTL generates HTML.
When each layer stays focused on its job, the application becomes easier to understand and maintain.
4. Caching is part of the architecture
Performance isn't just about writing fast Java code.
AEM is designed so that many requests never reach Java at all.
The CDN and Dispatcher can often return a cached response immediately, which is one of the reasons AEM scales well for high-traffic websites.
5. Learn the architecture before the APIs
Many developers try to memorize annotations like @Model or @ValueMapValue before understanding how a request moves through the system.
In my experience, it's much easier to learn those APIs once you understand the overall architecture.
Build the mental model first.
The implementation details become much easier afterward.
Final Thoughts
When I first started working with AEM, I spent a lot of time learning individual technologies.
I knew what HTL was.
I knew what Sling Models were.
I knew what Dispatcher did.
But they felt like separate pieces.
The breakthrough came when I stopped looking at them individually and started thinking about the journey of a single request.
A browser sends a request.
Dispatcher decides whether it should continue.
Sling finds the content.
The component is selected.
A Sling Model prepares the data.
An OSGi Service performs reusable business logic when needed.
HTL generates HTML.
The browser renders the final page.
Once you understand that journey, AEM stops feeling like a collection of Adobe-specific technologies and starts feeling like a well-organized system where every layer has a clear responsibility.
That mental model is the foundation for everything else you'll learn.
Continue the Series
You've now seen the major building blocks that make up an AEM application.
In the next article, we'll slow everything down and follow a single browser request through the platform. Rather than introducing new technologies, we'll focus on how they interact during one complete request lifecycle.
Understanding that flow is one of the most valuable skills you can develop as an AEM engineer because it directly influences debugging, performance tuning, and component design.
Next Article → Part 2: The Complete AEM Request Lifecycle
Series Roadmap
- Part 1: Understanding Adobe Experience Manager Architecture (Current)
- Part 2: The Complete AEM Request Lifecycle
- Part 3: Inside Apache Sling
- Part 4: Sling Models & Dependency Injection
- Part 5: OSGi Services Explained
- Part 6: HTL Explained
- Part 7: Dispatcher Deep Dive
- Part 8: Building Enterprise Components in AEM
- Part 9: React + Adobe AEM Cloud Service
- Part 10: From Development to Production
By the end of this series, you'll not only understand how AEM works internally but also how its architectural layers fit together to support large-scale, enterprise applications.
Masoud
July 4th, 2025