Adobe · Edge Delivery Services

Edge Delivery
Architecture

Crosswalk (Universal Editor) + Experience Workspace

Two ways to author content, and one pipeline that delivers it. Content and code ship on separate tracks, so neither one waits on the other. And because every publish comes out as plain semantic HTML, a browser, a mobile app, and a screenless device can all read from the same source.

Adobe Architecture Overview September 2026
The model at a glance

What makes Edge Delivery different

01

Two surfaces, one pipeline

Crosswalk (the Universal Editor on AEMaaCS) and Experience Workspace (da.live) only differ in where the content lives and how it's mounted. From the Admin Service onward, they're the same system.

02

Content and code on separate tracks

Authors publish through the Admin Service, and developers ship through Code Sync. Neither one waits on the other, and that's really the heart of how EDS works.

03

Preview vs. live, by branch

Every branch resolves to its own preview at <branch>--<repo>--<owner>.aem.page and its published version at .aem.live. Your production domain sits in front of .aem.live through your CDN.

What the browser gets

Edge delivers semantic HTML
GET /page → <div class="hero">…</div>
Browser runs decorate()
scripts.js enhances each block in place
Interactive, styled blocks
Adobe · Edge Delivery ServicesArchitecture Overview
End to end

The full delivery pipeline

Explore the full interactive board for more detail: wovea.live board ↗

AUTHORPUBLISHORCHESTRATESTORECOMPOSEDELIVERCONSUME AEM Sites + Universal EditorCrosswalk · JCRExperience Workspaceda.liveGitHub Repositoryblocks · fstab.yamlAEM Delivery Endpointcrosswalk mountDA Content Sourcedoc mountSidekick / Publishpreview + publishAEM Code SyncGitHub AppAEM Admin Servicethe orchestratorContent Busnormalized pagesMedia Busmedia_<hash>Code BusJS · CSS · blocksRendering PipelinesHTML · JSON · mediaExperience Compositionedge computeEdge FunctionsAdobe-managed CDN onlyProduction CDNDNS · TLS · cacheCache Purgeon publish or code-syncBrowser / Clientsemantic HTMLMobile Appweb componentIoT / AmbientJSON polling preview pullstriggerswritessyncs codecontentcoderendersorigininvalidatefull HTMLat the edge
Service Datastore Queue / event API / representation
Adobe · Edge Delivery ServicesArchitecture Overview
Authoring

The two authoring paths

The two paths only differ in where the content lives and how the repo mounts it. Once you get past the Admin Service, they're the same system.

Crosswalk — AEM Sites + Universal Editor

This is in-context, component-based authoring. The content lives in the JCR on AEM as a Cloud Service, and the Universal Editor lets you edit the rendered page directly, mapping each component to an EDS block.

mount → /bin/franklin.delivery/<owner>/<repo>/<ref>/*

Experience Workspace — da.live

Adobe's EDS-native document CMS. You edit documents right in the browser, with versioning built in, and you don't have to mount Google Drive or SharePoint to do it.

mount → content.da.live/<org>/<site>

GitHub Repository

This holds the site code — blocks, scripts, and styles — along with fstab.yaml (the mount points), paths.json (which maps AEM paths to URLs), and the component definitions and models that drive the Universal Editor.

adobe/aem-boilerplate · Vanilla JS · CSS

Think of Crosswalk and Experience Workspace as two front doors to the same building. The repo's fstab.yaml decides which mount a site uses, and from there, everything downstream is identical.
Adobe · Edge Delivery ServicesAuthoring
Components and blocks

What's the difference between a component and a block?

Component is a familiar idea in front-end development: small pieces of functionality that you nest inside bigger ones. A block takes a flatter approach.

The component model

You compose by nesting. A button and an image go inside a teaser, and a teaser goes inside a carousel. That's great for reuse, but every layer adds another wrapper, and a framework has to assemble and hydrate the whole tree in the browser. What you end up shipping is deep, heavy markup — the thing people call “div soup.”

<Carousel>
  <Teaser>
    <Button>Shop</Button>
    <Image src="hero.jpg" />
  </Teaser>
</Carousel>

How a block is different

A block flattens that tree into a single unit, and blocks don't nest: a section holds blocks, and a block holds content, but a block never holds another block. It arrives as semantic HTML and gets enhanced by a decorate() function in the browser — plain JavaScript, no framework. You give up some of the encapsulation a component gives you, and in return the page stays flat and fast.

<div class="carousel block">
  <picture><img …></picture>
  <h2>…</h2>
  <a class="button">…</a>
</div>
So it's a trade. Components buy you reuse and encapsulation, but you pay for it in markup depth and a runtime to put it all together. A block moves that composition into the content instead, so what actually ships to the browser stays flat and semantic.
Adobe · Edge Delivery ServicesComponent & block
Orchestration & storage

The Admin Service and the three buses

AEM Admin Service — the orchestrator

When you preview, it pulls from the content source, normalizes it, and writes to the Content and Media Buses (.aem.page).

When you publish, it promotes that content to the delivery tier (.aem.live) and purges the CDN.

normalize preview publish purge Content source Admin Service .aem.page preview tier .aem.live live tier CDN

admin.hlx.page API · Adobe-managed

Content Bus

Normalized page content in both preview (.aem.page) and published (.aem.live) states, per branch.

Media Bus

Content-addressable image & video storage (media_<hash> filenames), so identical assets are stored and cached once.

Code Bus

JS, CSS, and block code synced from GitHub and versioned per branch. It deploys independently of the content.

The buses are Adobe-managed storage, and the specific backing store is really an implementation detail. If you want the full picture, the architecture reference covers it: aem.live/docs/architecture.
Adobe · Edge Delivery ServicesOrchestration & storage
Edge → delivery

Composition, rendering, and delivery

Experience Composition Service

Edge compute that composes content from the Content, Media, and Code Buses into the final response. It serves both <branch>--<repo>--<owner>.aem.page and .aem.live.

Rendering Pipelines — HTML / JSON / Media

Separate pipelines turn the bus content into semantic HTML, query-index JSON, and optimized media. This is also where head.html, metadata, and redirects get applied.

Production CDN

A customer- or Adobe-managed CDN (Akamai, Fastly, Cloudflare, or CloudFront) fronts the production domain and handles DNS and TLS. It holds the cached copy the public actually hits.

Cache Purge / Invalidation

Publish and code-sync events emit targeted purges, so only the changed paths and their dependents get invalidated. There's never a full flush.

Every branch resolves to a preview at .aem.page and a published version at .aem.live. Your production domain sits in front of .aem.live through the CDN, and the purge queue keeps that cache in sync for you.
Adobe · Edge Delivery ServicesEdge & delivery
Output formats

The same content, in whatever shape you need

The same Content Bus entry is addressable three different ways, and the author never has to pick one. Whatever's consuming it — a browser, a native app, a device — just asks for the shape it can use.

GET /path
Full HTML page
Semantic markup, the default web response. → Browser
GET /path.plain.html
Body-only fragment
Just the page body, no chrome. → Web component · app
GET /*.json
Structured data
Content as data, no client runtime. → Apps · IoT · integrations

Page as JSON — any page → structured JSON

{
  "metadata": {
    "title": { "text": "Exploring AmmoVault…" },
    "canonical": { "href": "…/ammovault-ammunition-reserve" }
  },
  "content": [
    { "section": [ { "type": "block",
        "name": "spotlight", "content": […] } ] }
  ]
}
live example ↗

Structured content — schema-backed fields

{
  "metadata": { "schemaName": "doctors-schema" },
  "data": {
    "name": "Tahmina Aafreen, MD",
    "primarySpecialty": "Obstetrics and Gynecology",
    "languages": ["English","Hindi","Urdu"],
    "acceptingNewPatients": true
  }
}
live example ↗
Adobe · Edge Delivery ServicesRepresentations
Consumers

One publish reaches every channel

Here's the key idea: all content is structure. Semantic HTML is structured content too, just the same authored source expressed as tags. So no consumer is decorating a blob; each one takes the shape it can read, and the structure carries through.

Browser / Client

It gets semantic HTML right away, then scripts.js decorates the DOM and lazy-loads the blocks. Core Web Vitals is the target the whole architecture is built around.

Mobile App

A native shell hosts the web component for authored screens like promos, help, legal, and campaign content, and pulls its lists, nav, and config from JSON. You can ship content without an app-store release.

Web Component / Block Embed

A custom element fetches a .plain.html fragment and runs the same block-decoration code from the Code Bus. That lets you render authored content anywhere, with no EDS page around it.

IoT / Ambient Device

A kiosk, digital sign, wearable, or voice surface with no browser engine. It polls the JSON endpoints and renders natively, from the same authored source, with no dependency on markup.

It's structure all the way down. HTML, .plain.html, and JSON are just three encodings of one structured source, and semantic HTML is structure, not styling. That's why a browser, a native app, and a screenless device can all consume the same publish without needing a separate content model.
Adobe · Edge Delivery ServicesConsumers
Performance

Why EDS pages score so well on Lighthouse

You don't tune a high score in after the fact. It falls out of how the page is built and served: no framework runtime, semantic HTML from the edge, and a disciplined three-phase load sequence.

① Eager
Only what the LCP needs loads first: the first block, its CSS, and the hero image.
② Lazy
Remaining blocks and below-the-fold sections load after the LCP paints.
③ Delayed
Analytics, tags and chat load ~3s later, off the critical path.

Fast LCP

Semantic HTML comes straight from the CDN edge, so there's no server render and a low TTFB. The LCP image is prioritized and delivered as a responsive <picture> in modern formats from the Media Bus.

Near-zero CLS

Explicit width/height on every image, reserved block space, and a controlled font strategy mean the layout never reflows as it loads.

Low TBT / INP

It's vanilla JS with no hydration. Blocks decorate progressively in small steps on the main thread, and third-party weight is held back to the delayed phase.

And it's enforced, not just hoped for. A Lighthouse/PSI budget runs in CI against the branch preview, and RUM measures Core Web Vitals on real traffic. So you catch a regression before it merges, and you see it after.
Adobe · Edge Delivery ServicesPerformance
Search and AI visibility

What flat HTML means for SEO and GEO

The same flattening that makes a page fast also makes it legible to machines. But the stakes are different for search engines than they are for AI answer engines.

SEO — Google renders your JS

Deep component trees usually still get indexed, so the cost here is indirect, through speed. Core Web Vitals is a confirmed ranking signal, and Lighthouse penalizes a DOM over ~800 nodes (warning) or ~1,400 (error), or a nesting depth over 32 — which is exactly what component nesting produces.

Flat HTML is faster on INP and LCP, and it's guaranteed to be indexable because there's no render step to fail.

GEO — AI crawlers don't render your JS

Across 500M+ GPTBot fetches, not one executed JavaScript (Vercel / MERJ). GPTBot, ClaudeBot, and PerplexityBot only read the initial HTML, so a page that ranks #1 on Google can be invisible to ChatGPT if it's client-rendered.

A block's semantic HTML is in the response by default, and the same content is served as JSON on top of that.

So flattening isn't just about performance anymore; it's about being seen at all. Google will render your “div soup,” but AI answer engines won't — and AI-search referral traffic grew ~16× from 2024 to 2026. Flat, semantic, server-delivered HTML (plus JSON) is legible to both.

Sources: Vercel / MERJ AI-crawler analysis · Lighthouse DOM-size audit · Google Search Central — Page Experience

Adobe · Edge Delivery ServicesSEO & GEO
Part II — Developer workflow

Branching, localhost, and Code Sync

This is the code track, start to finish. Authors publish on their own separate track through the Admin Service, so a deploy never blocks a publish, and a publish never waits on a deploy.

A

Local code, remote content

aem up serves your working tree and proxies everything else from the preview tier. There's nothing to install beyond the CLI: no seed data, no database, and no drift between machines.

B

The branch is the environment

Push a branch and it resolves to its own preview URL seconds later, running that branch's code against the same shared content. You review on a real URL, not a screenshot.

C

This is the code track

It runs independently of authoring, so a deploy never blocks a publish. And rolling back is just a git revert.

D

CI is yours, deployment is Adobe's

Actions gates the merge, while Code Sync just copies files and gates nothing. They run in parallel, so branch protection on main is what really gates a release.

Adobe · Edge Delivery ServicesDeveloper workflow
End to end

The developer workflow, start to release

Walk the full interactive board for more detail: wovea.live board ↗

LOCALBRANCHCODE SYNCPREVIEWREVIEWRELEASECI — YOURS Local Working Treegit clone · no buildaem up (AEM CLI)proxy · live reloadlocalhost:3000code + real contentAuthored Contentshared previewFeature Branchpush earlyGitHub Repositorysource of truth.github/workflowsCI as codeGitHub Actions — CIlint · test · PSIAEM Code Syncevery branchCode Bus / branchisolated codeBranch Preview URL…--owner.aem.pagePull Request + Reviewrequired checksMerge to mainthe releaseCache PurgetargetedProduction Site…aem.live · CDNRUM + Performancereal-user datastage — long-livedOPTIONAL detour content proxycommitCode Sync watches every branchsyncs codecode for branchopen PRpreview = review artifactapprove + mergeemits purgeinvalidate changedreal-user data / releaseregressions → the next branchCI config in repoon push / PRrequired checks · PSI budgetoptional UAT detour
Service Datastore Queue / event Environment / URL
Adobe · Edge Delivery ServicesDeveloper workflow
The inner loop

Local code, remote content

aem up: your whole local environment

It starts a proxy that serves code from your working tree and pulls content from the remote preview, and it live-reloads on save.

npx @adobe/aem-cli

Local Working Tree

Just a git clone: blocks/, scripts.js, styles.css, head.html, fstab.yaml. No build step, no bundler, no node_modules in what gets served. The files you edit are the files that ship.

Local Working Tree
edit · save
aem up
serves working tree, live reload
localhost:3000
local code + real authored content
▲ content pulled via Content Proxy from the shared preview (main--repo--owner.aem.page)
Authored Content — shared preview
every dev + branch reads the same copy
The whole loop takes seconds: edit, save, reload. There's nothing to install beyond the CLI, no content to seed, and no drift between your machine and anyone else's.
Adobe · Edge Delivery ServicesDeveloper workflow
The outer loop

The branch is the environment

Feature Branch
git checkout -b
GitHub Repo
push
Code Sync
watches every branch
Code Bus / branch
this branch's code
Branch Preview URL
live in seconds

Push early

In EDS a branch isn't a step toward an environment; the branch is the environment. Push feature/hero-block and it becomes a full site.

Branch Preview

You get feature-hero--repo--owner.aem.page: a full, shareable environment running that branch's code against the same shared content, with no per-branch copy.

PR + Review

People review against the preview URL itself, so the preview URL is the review artifact, gated by the required status checks.

There's nothing to provision, nothing to tear down, and no waiting for a staging slot. That's why review happens on a real URL instead of a screenshot.
Adobe · Edge Delivery ServicesDeveloper workflow
CI and deployment

CI is yours, deployment is Adobe's

CI — GitHub Actions (yours)

This runs on GitHub-hosted runners, on push and pull_request: ESLint and Stylelint, unit tests, and a Lighthouse/PSI budget against the branch preview URL. It reports back as required status checks.

It's defined in .github/workflows, so your CI is code too, versioned in the same repo and reviewed in the same PR.

Deployment — Code Sync (Adobe's)

You install it once on the repo. It watches every branch, not just main, and pushes each commit to the Code Bus within seconds. There's no build, no bundling, and no test step.

It runs in parallel with CI, not after it, and it gates nothing.

A branch preview goes live whether or not CI is green. That's handy while you're iterating, and it's why branch protection on main is the gate that actually matters.
Adobe · Edge Delivery ServicesDeveloper workflow
Release

Merging to production, and the optional stage step

The default path

Merging to main is the release. There's no build, no deploy job, and no maintenance window. Code Sync picks up main, emits a targeted purge, and the change is live at …--owner.aem.live behind the CDN in seconds. To roll back, you git revert.

Merge to main
Cache Purge
Production Site

Optional — long-lived stage

This is a permanent branch that feature branches merge into first, before they promote to main. It earns its keep in exactly one case: because fstab.yaml is per-branch, stage can mount a different content source, which is the only real content isolation EDS gives you. The cost is drift and batched merges.

stage branch
Stage env (UAT)
Promote to main
Take the detour when a client needs formal UAT or a separate authoring environment. Otherwise skip it: every branch is already a full preview, so a permanent stage mostly re-creates what you already have.
Adobe · Edge Delivery ServicesDeveloper workflow
Reference

Component inventory

ComponentTypeOwnerRole
AEM Sites + Universal EditorServiceAuthoring — structuredIn-context component authoring; content in JCR on AEMaaCS.
Experience Workspace — da.liveServiceAuthoring — documentEDS-native document CMS with versioning.
GitHub RepositoryServiceDevelopmentBlocks, styles, fstab.yaml, paths.json, UE component models.
Sidekick / Publish TriggerServiceAuthoringFires Preview and Publish from UE or da.live.
AEM Admin ServiceServiceAdobe-managedOrchestrator: normalize → Content/Media Bus → promote → purge.
AEM Code SyncServiceAdobe-managedGitHub App syncing merged code to the Code Bus.
Content BusDatastoreAdobe-managedNormalized page content, preview + published, per branch.
Media BusDatastoreAdobe-managedContent-addressable media (media_<hash>).
Code BusDatastoreAdobe-managedJS/CSS/block code from GitHub, versioned per branch.
Experience Composition ServiceServiceAdobe-managedEdge compute composing buses into the final response.
Rendering PipelinesServiceAdobe-managedHTML / JSON / media pipelines; head.html, metadata, redirects.
Production CDNServiceCustomer infrastructureAkamai/Fastly/Cloudflare/CloudFront; DNS, TLS, cache.
Cache Purge / InvalidationQueueAdobe-managedTargeted purge of changed paths + dependents.
Browser · Mobile App · Web Component · IoTServiceEnd user / Mobile / DeviceConsumers of HTML, .plain.html fragments and JSON.
RUM / Operational TelemetryServiceAdobe-managedSampled real-user monitoring; feedback into code + content.
Adobe · Edge Delivery ServicesReference
FAQ · 1 of 3

Performance, cost, and security

QWhy is this faster? What's actually different about performance?

The page ships as semantic HTML straight from the CDN edge, with no server render and no framework to boot up, so TTFB and LCP stay low. Then scripts.js loads blocks in three phases — eager, lazy, delayed — which keeps the main thread free for good INP, and images carry fixed dimensions so nothing reflows and CLS stays near zero.

QDoes this reduce our licensing or infrastructure cost? depends on your setup

Often it does, but it depends on your contract. Delivery is Adobe-managed, so there's no publish or dispatcher fleet for you to run and patch. What it does to AEM licensing depends on what you keep: Crosswalk still uses AEMaaCS for authoring, while Experience Workspace doesn't.

QIs this secure? Are we more exposed without a publish/dispatcher layer? depends on your setup

It's a different model, not a weaker one. There's no running publish app or dispatcher for an attacker to reach, because delivery is static content from the edge, which is a much smaller attack surface than a live Java app. Whether your overall posture improves depends on what you're replacing.

QWhat's the security model at the origin, and who's responsible for what? confirm with Adobe

There's no OSGi/Sling runtime at the origin to patch — it serves pre-rendered content from the buses, not a live application. Adobe owns the edge and its patching; you own your block code, your content sources, and your CDN and WAF rules. Confirm the exact split with Adobe for your contract.

Adobe · Edge Delivery ServicesFAQ
FAQ · 2 of 3

Integration, reuse, and operations

QHow do we integrate backend services, APIs, or commerce data without Sling/OSGi?

You integrate at the edge or in the browser instead of a Java layer. Blocks call your APIs client-side for dynamic data like pricing and inventory, and AEM Edge Functions can compose or guard requests server-side, with their own KV store. Read-heavy data can also come through structured JSON.

QCan existing AEM components or client libraries be reused, or is it all rebuilt as blocks?

Mostly rebuilt, and this is the honest one. Blocks are vanilla JS and CSS, not HTL/Java components or clientlibs, so existing components don't port directly. You can carry over design, content models, and a lot of CSS, but plan for a front-end rebuild, not a lift-and-shift.

QWhat does CI/CD look like — is Cloud Manager still in the picture?

For the EDS site it's GitHub-driven, not Cloud Manager. Code Sync deploys from your repo to the Code Bus on every push, and GitHub Actions gates the merge. If you're on Crosswalk you still have AEMaaCS for authoring, but the front-end code path doesn't go through Cloud Manager pipelines.

QHow do we monitor and debug production without a traditional Publish instance?

You lean on RUM and the repo, not a server console. Adobe's operational telemetry gives you real-user Core Web Vitals per release, and the Sidekick plus branch-preview URLs let you reproduce issues. Since delivery is static content, most problems trace back to content in a bus or code in the repo.

Adobe · Edge Delivery ServicesFAQ
FAQ · 3 of 3

SEO and AI readiness

QHow do redirects, metadata, and SEO get managed without Dispatcher or HTL templates?

These move into content and config instead of templates. Redirects live in a spreadsheet in the repo, metadata comes from a metadata sheet and per-page values, and head.html sets the global head. The rendering pipeline applies all of it, so you manage SEO as content, not Dispatcher rules.

QIs our site AI/LLM-ready out of the box, or is there still work to do?

You start well ahead, but it's not zero work. Pages ship as semantic HTML in the first response and the same content is available as JSON, so AI crawlers can actually read you — which is where most sites fail. What's still on you is good heading structure, real metadata, and JSON-LD where you want rich answers.

QIs the semantic HTML optimized for AI search / GEO out of the box?

Largely yes, because of how it's built. The content is in the initial HTML, so crawlers that don't run JavaScript still see it, and it's also addressable as JSON for systems that prefer structured data. That's the biggest GEO lever, and you get it without extra work.

Adobe · Edge Delivery ServicesFAQ
Wrapping up

Why this approach works

2

Authoring surfaces

Crosswalk and Experience Workspace share one pipeline, so you pick the front door per site, not per architecture.

2

Independent tracks

Content and code deploy separately, so neither release path blocks the other.

3

Representations

HTML, .plain.html, and JSON all come from one publish, so every channel is served without a rebuild.

1

Target

It's all aimed at Core Web Vitals: semantic HTML from the edge, decorated on the client, measured by RUM.

If there's one thing to take away: decouple who publishes from how it's delivered, serve it from the edge, and let each consumer take the shape it can use.
Adobe · Edge Delivery ServicesSummary
Use ← → arrow keys · Press F for fullscreen · Print to PDF for a shareable copy