N
Naveenr.dev
Chapter 09
28 min read2026-06-30

EDS Limitations and Alternatives

EDS limitations and alternatives. Covers server-side logic, workflow, JCR queries, AEM Forms, MSM, Content Fragments, DAM schemas, and Dispatcher rules.

Content Objective

This chapter covers:

  • Every significant EDS limitation with honest architectural assessment
  • Practical alternatives for each limitation (not workarounds — real solutions)
  • When the limitation is fundamental (architecture) vs tooling (can be built)
  • Hybrid patterns that combine AEM and EDS strengths
  • The decision framework for "should this project use EDS?"
  • How experienced architects scope EDS projects to avoid hitting walls late

This chapter is for architects and senior developers.

The biggest risk in any EDS project is discovering a hard limitation after the project has started. This chapter is designed to surface those limitations before the project starts.

I want to be direct: some of these limitations are temporary tooling gaps that Adobe will close. Some are fundamental architectural constraints that will not change. I will distinguish between them.


How to Read This Chapter

For each limitation, I rate it on two dimensions:

Severity: How often does this matter in real projects?

  • 🔴 High — affects most enterprise projects
  • 🟡 Medium — affects some projects depending on requirements
  • 🟢 Low — affects only specialized use cases

Permanence: Is this a fundamental architectural constraint or a tooling gap?

  • 🏗️ Fundamental — will not change (architecture-level constraint)
  • 🔧 Tooling — may improve with product roadmap

1. Server-Side Business Logic

Severity: 🔴 High | Permanence: 🏗️ Fundamental

What you cannot do

You cannot run Java code, OSGi services, Groovy scripts, or any server-side computation during the page render cycle. There is no Sling resolution, no component rendering chain, no servlet that runs before the HTML is delivered to the browser.

Specific capabilities lost:

  • Sling Models with complex data aggregation
  • JCR queries returning content from multiple paths
  • Real-time inventory / pricing lookups during render
  • Server-side A/B test variant selection
  • Rate-limited operations (don't want to expose API keys to browser)
  • Data transformation that depends on server state (session, user role)

Why this is fundamental

EDS delivers pre-built HTML from a CDN edge cache. CDN edge nodes do not run Java application servers. This is a fundamental architectural choice — it is why EDS achieves its performance guarantees. Allowing server-side computation would require an origin hit on every request, eliminating the performance model.

What to do instead

Option 1: External API pattern

Move server-side logic to an external microservice (AWS Lambda, Azure Function, Node.js server). Your block JS calls this API:

export default async function decorate(block) {
  const productId = block.querySelector('div div').textContent.trim();

  // External API handles all server-side logic
  const response = await fetch(`https://api.company.com/products/${productId}`);
  const product = await response.json();

  block.innerHTML = '';
  // Render product data
}

Security consideration: Be careful what you expose via client-side API calls. Rate limiting, authentication, and CORS configuration are now your responsibility on the API server.

Option 2: Pre-compute to JSON sheets

If the data is not real-time, pre-compute it to a Google Sheets or SharePoint spreadsheet. EDS exposes this as /data/products.json. Your block fetches it.

Option 3: xwalk path (if data is in AEM)

If the data is in AEM JCR and you are using Universal Editor, a Sling Servlet on the AEM author/publish instance can provide the data via a JSON endpoint that your block calls.


2. Multi-Step Content Approval Workflow

Severity: 🔴 High | Permanence: 🔧 Tooling (partially)

What you cannot do

There is no native multi-step workflow in pure EDS:

  • No approval chains (Author → Manager → Legal → Publish)
  • No custom process steps with Java logic
  • No deadline-based escalation
  • No workflow inbox
  • No audit trail of who approved what

Why this matters

In regulated industries (healthcare, financial services, pharma), content must pass through multiple reviewers before publishing. The inability to enforce this workflow is a compliance risk.

What to do instead

Option 1: xwalk + AEM Workflow (strongest option)

Since xwalk content lives in AEM JCR, standard AEM workflows are available. A workflow that requires legal review before the bin/franklin.delivery servlet makes content available to the EDS edge can enforce the approval chain.

Author edits in Universal Editor
  ↓
Clicks "Submit for Review" (triggers AEM Workflow)
  ↓
Workflow routes to Manager
  ↓
Manager approves → routes to Legal
  ↓
Legal approves → workflow completes → content available for Preview
  ↓
Author can now click Preview/Publish

This requires custom Sidekick plugin development to intercept the Preview action and verify workflow state before allowing it.

Option 2: Branch-based review (for DA authoring)

Authors work on a feature branch. A PR is opened for review. Reviewers comment and approve in GitHub. Merge to main triggers the preview pipeline.

This is developer-familiar but not author-friendly for non-technical teams.

Option 3: External workflow tool + Sidekick plugin

Integrate with Workfront, Jira, or a custom approval API. A custom Sidekick plugin checks the external system before allowing Preview/Publish:

// custom-sidekick-plugin.js
export async function onPreview(event) {
  const pageUrl = window.location.href;
  const approvalStatus = await fetch(`https://approval-api.company.com/status?page=${pageUrl}`);
  const { approved } = await approvalStatus.json();

  if (!approved) {
    event.preventDefault();
    showMessage('This page requires approval before preview.');
  }
}

3. JCR Queries and Complex Content Traversal

Severity: 🔴 High | Permanence: 🏗️ Fundamental

What you cannot do

You cannot run JCR queries (XPath, SQL2, QueryBuilder) against the content repository:

  • Find all pages with a specific template
  • Find all assets tagged with a specific tag
  • Find all pages modified in the last 7 days
  • Find all components of a specific type across the site
  • Traverse deep node trees programmatically

What EDS provides instead: Query API

The Query API provides a pre-built JSON index of page metadata. It is powerful for listing pages but has limits:

JCR Query CapabilityQuery API Capability
Query by any JCR propertyQuery only indexed metadata fields
Real-time resultsUpdated only on page publish
Deep traversal (child pages N levels)Flat index only
Query assets in DAMNot available
Complex boolean conditionsClient-side JS filter
Result count / pagination at query levelClient-side slice
Faceted searchNot supported natively
Full-text search (across all node content)Title/description only

What to do instead

For content listings (blog index, news archive, product catalog): Query API + client-side filter is usually sufficient. Index the fields you need to filter on.

For complex search: Integrate with Adobe Search & Promote, Algolia, or an external search service. Index content into the search service on publish. Your search block calls the search API.

// blocks/search/search.js
export default async function decorate(block) {
  const input = document.createElement('input');
  block.append(input);

  input.addEventListener('input', async (e) => {
    const query = e.target.value;
    if (query.length < 3) return;

    // External search service
    const results = await fetch(`https://search.algolia.io/query=${query}`);
    renderResults(await results.json());
  });
}

For DAM asset queries: Use AEM Assets API (available via REST from your block JS, with authentication handled client-side via Adobe IMS).


4. AEM Forms

Severity: 🟡 Medium | Permanence: 🔧 Tooling

What you cannot do

AEM Forms (Adaptive Forms) is not available in EDS:

  • No form data model integration
  • No adaptive form rendering
  • No submit actions with JCR storage
  • No form data prefill from JCR
  • No form workflow integration
  • No AEM Forms Portal

What to do instead

Option 1: Simple HTML forms with external submission

For contact forms, registration forms, newsletter signups:

// blocks/contact-form/contact-form.js
export default function decorate(block) {
  const form = document.createElement('form');
  form.innerHTML = `
    <input type="text" name="name" placeholder="Name" required>
    <input type="email" name="email" placeholder="Email" required>
    <textarea name="message"></textarea>
    <button type="submit">Submit</button>
  `;

  form.addEventListener('submit', async (e) => {
    e.preventDefault();
    const data = Object.fromEntries(new FormData(form));
    await fetch('https://submit.company.com/contact', {
      method: 'POST',
      body: JSON.stringify(data),
    });
  });

  block.append(form);
}

Option 2: Forms as a Block (Franklin-native approach)

The EDS boilerplate includes a forms approach using JSON-defined form schemas authored as a spreadsheet. This is less powerful than Adaptive Forms but authoring-friendly.

Option 3: Adobe Workfront Forms / third-party

For complex enterprise forms with conditional logic, multi-step flows, and integrations: use Formstack, Typeform, or a custom form service.

Option 4: Headless AEM Forms (Edge Delivery for Forms)

Adobe is investing in EDS-compatible Adaptive Forms rendering. This is an emerging capability (as of 2026) — check the Adobe roadmap.


5. Multi-Site Manager (MSM) and Live Copy

Severity: 🔴 High | Permanence: 🏗️ Fundamental

What you cannot do

AEM MSM is not available in EDS:

  • No live copy relationships between sites
  • No rollout configurations (which content is pushed from blueprint to live copy)
  • No synchronization (changes in blueprint auto-propagate to live copies)
  • No disconnection from live copy at component/page level
  • No language master + translation workflow integration via MSM

Why this matters

MSM is used for:

  • Multi-country/multi-brand sites where 80% of content is shared
  • Language master → regional variations
  • Corporate template enforcement with local overrides

What to do instead

Option 1: Folder structure as content hierarchy

Multiple locales under shared folder structure, with page-level duplication:

/en/          ← English master
/fr/          ← French copy (manually maintained)
/de/          ← German copy (manually maintained)

This is MSM without the sync. Changes to the English master must be manually propagated to each locale. For small sites (under 100 pages), this is manageable. For large sites, it becomes a maintenance problem.

Option 2: Shared blocks + locale-specific content

Structure your site so the EDS blocks (code + layout) are shared but content pages are locale-specific. The developer work is the same across locales; only content differs.

Option 3: xwalk with AEM MSM

Since xwalk content is in AEM JCR, AEM MSM works with xwalk content. You get live copy relationships, rollout, and language masters — plus EDS delivery performance. This is the best option for complex multi-site requirements.

Architect recommendation: For projects with 5+ locales and significant shared content, the xwalk path with AEM MSM is strongly recommended. Pure DA authoring cannot replicate MSM.


6. Content Fragments and Headless Architecture

Severity: 🟡 Medium | Permanence: 🔧 Tooling

What you cannot do

EDS does not natively support AEM Content Fragments:

  • No Content Fragment models (schema definition)
  • No GraphQL layer for Content Fragments in EDS
  • No Experience Fragment integration (natively — there is a workaround)
  • No structured content reuse across pages via fragment reference

Experience Fragments: There IS a Workaround

EDS has a native Fragment block for Experience Fragments:

| Fragment                    |
|-----------------------------|
| /content/experience-fragments/shared/nav-cta |

The Fragment block fetches the fragment URL, inlines its HTML into the current page. This works for visual component reuse but not for structured data reuse.

What to do instead for Content Fragments

Option 1: JSON sheets for structured data

Define a spreadsheet schema for your content type. Authors fill in the spreadsheet. The spreadsheet becomes a JSON API:

Product Catalog spreadsheet:
| name    | price  | category | description     |
|---------|--------|----------|-----------------|
| Item A  | $99    | tools    | Item description|

Available at: /data/products.json

This is sufficient for simple structured content (pricing tables, team members, office locations, FAQ items).

Option 2: External Headless CMS + EDS

For truly complex structured content (rich schemas, nested models, complex relationships), use a headless CMS alongside EDS:

  • AEM Content Fragments via GraphQL (if already licensed)
  • Contentful, Hygraph, Sanity (third-party)
  • A custom data API

Your EDS block fetches from the headless API:

export default async function decorate(block) {
  const endpoint = block.querySelector('div div a')?.href;
  const data = await fetch(endpoint).then(r => r.json());
  // Render structured content
}

7. AEM Assets DAM Capabilities

Severity: 🟡 Medium | Permanence: 🔧 Tooling (partially)

What you cannot do

Full AEM DAM features are not available in EDS (DA authoring):

  • Asset metadata schemas with custom fields
  • Automated asset workflows (watermarking, rendition generation beyond web renditions)
  • Asset Collections
  • Asset Share Commons (external portal)
  • Smart Crop (Content-aware) — partially available
  • Adobe Sensei asset tagging
  • Rights Management
  • Video transcoding via DAM workflows

What is available

  • Image delivery with automatic WebP conversion and responsive sizing (Media Bus)
  • Basic asset upload and reference in authored content
  • For xwalk: full AEM DAM since content is in JCR

8. Component-Level Access Control

Severity: 🟡 Medium | Permanence: 🏗️ Fundamental

What you cannot do

AEM's JCR ACL system provides component-level, page-level, and path-level access control:

  • Author A can edit the hero component but not the navigation
  • A specific author group can only publish to a specific sub-tree
  • Content is invisible to authors without read permission

EDS does not replicate this:

  • No component-level access control in UE (all authors can edit all blocks on a page they have access to)
  • No per-path author restrictions in DA

What to do instead

For xwalk: Since content is in JCR, standard AEM ACLs apply at the page level. Author permissions can be set per content path.

For DA: Access control is at the document/folder level in da.live. Granular component-level restrictions are not available.


9. Dispatcher: Custom Caching and URL Rewriting

Severity: 🟡 Medium | Permanence: 🏗️ Fundamental

What you cannot do

  • Custom Apache rewrite rules (RewriteRule)
  • Fine-grained cache control per URL pattern
  • Authentication-based cache bypass
  • Custom error pages beyond 404
  • URL vanities that differ from content structure
  • IP-based restrictions at the edge

What to do instead

Custom URL rewriting: EDS supports a redirects.xlsx spreadsheet that defines URL redirects. For /old-path → /new-path redirections, this is sufficient. For complex RewriteRule logic (regex with conditions), a CDN layer (Fastly, Cloudflare) in front of EDS is required.

Authentication-based content: Handle authentication client-side. Protected content should not be in the EDS page itself — fetch it from an authenticated API after the user logs in.

Custom caching: EDS CDN cache behavior is managed by Adobe and is intentionally simple (cache everything, invalidate on publish). Complex per-URL caching strategies require a custom CDN.


10. Digital Rights Management and Gating

Severity: 🟢 Low | Permanence: 🏗️ Fundamental

What you cannot do

  • Paywall/subscription gating at the server side
  • DRM on delivered assets (videos, PDFs)
  • Session-based content visibility (logged-in users see different content)

What to do instead

Client-side gating with an authentication service (Adobe IMS, Auth0, Okta):

// scripts/scripts.js (modified for gated sites)
const user = await checkAuth(); // Adobe IMS or similar
if (!user && isGatedPage()) {
  window.location.href = '/login';
}

The HTML is delivered to everyone, but client-side JS redirects unauthenticated users. For genuinely secure content (not just gated), do not put it in EDS page HTML — it should come from an authenticated API call after login.


The Architecture Decision Framework

Use this framework when evaluating whether a project should use EDS:

Strong EDS Fit

✅ Primarily editorial content (articles, landing pages, campaign pages)
✅ Authors are non-technical (DA authoring model)
✅ Performance is a primary requirement (Core Web Vitals, LHS 100)
✅ Content volume is high but structure is low (many pages, simple blocks)
✅ No multi-step approval requirement (or xwalk is acceptable)
✅ No complex server-side rendering needed
✅ No AEM Forms requirement
✅ Small component library (< 20 blocks)
✅ Developer velocity is prioritized
✅ Marketing team manages site content independently

EDS with AEM (xwalk path) Fit

✅ Needs EDS performance AND AEM capabilities
✅ Complex approval workflows required
✅ MSM/multi-site with content inheritance required
✅ Large existing AEM component library (gradual migration)
✅ AEM Assets DAM integration required
✅ Existing AEM investment should be preserved
⚠️ More complex setup (requires AEM Cloud instance)
⚠️ Content lives in JCR (not pure EDS content model)

Poor EDS Fit (Consider Traditional AEM)

❌ Application is primarily transactional (not editorial)
❌ Complex server-side personalization is required
❌ AEM Forms is central to the experience
❌ Deep JCR query requirements (search, complex listings)
❌ Per-component access control is a compliance requirement
❌ Content model is deeply hierarchical with complex inheritance
❌ Large regulated content library requiring strict workflow enforcement
❌ Team has deep AEM expertise and no JavaScript frontend skills

Hybrid Pattern: EDS + AEM in the Same Domain

Many enterprise projects use EDS and traditional AEM on the same domain:

www.company.com/         → EDS (marketing pages)
www.company.com/products → EDS (product catalog, editorial)
www.company.com/app/     → Traditional AEM (authenticated application)
www.company.com/forms/   → Traditional AEM Forms
www.company.com/search   → External search (Algolia/SearchPromote)

The CDN layer routes requests to the appropriate backend based on path. This allows each section of the site to use the technology best suited to its requirements.

This is the pattern most large enterprises will converge on: EDS for editorial speed and performance, traditional AEM for complex application functionality.


Summary: EDS vs AEM Capability Reference

CapabilityEDSAEMUse What?
Editorial page authoring✅ Excellent✅ GoodEDS
Component development✅ JS/CSS only✅ Full stackDepends on need
Performance / Core Web Vitals✅ Structural 100⚠️ Requires effortEDS
Multi-step approval workflow❌ Not native✅ Full engineAEM (or xwalk)
Component inheritance❌ None✅ Sling Resource MergerAEM
JCR / complex queries❌ None✅ Full QueryBuilderAEM
AEM Forms❌ Not available✅ Adaptive FormsAEM
MSM / Live Copy❌ None (DA) / ✅ (xwalk)✅ Full MSMAEM or xwalk
Editable template policies❌ None✅ FullAEM
Content Fragments (structured)❌ Not native✅ Full CF + GraphQLAEM
Server-side logic❌ None✅ Sling/OSGiAEM
Dispatcher custom rules❌ None✅ Apache rulesAEM (or CDN)
Experimentation / A/B✅ Built in⚠️ Requires TargetEDS
Deployment speed✅ git push⚠️ Pipeline requiredEDS
Authoring simplicity✅ Document authoring⚠️ Training requiredEDS
DAM at scale❌ Basic (DA) / ✅ (xwalk)✅ Full DAMAEM or xwalk
Multi-tenant single repo⚠️ CSS themes only✅ Overlay systemAEM
Scalability✅ CDN auto-scales⚠️ Requires infraEDS
Total cost (editorial site)✅ Lower⚠️ HigherEDS
Total cost (application site)⚠️ Higher (external APIs)✅ Self-containedAEM

Key Takeaways

  • EDS is the right choice for editorial-focused sites — marketing, campaigns, product documentation, news
  • AEM is the right choice for application-heavy sites — complex forms, transactional flows, deep personalization, regulated workflows
  • The xwalk path is the bridge — EDS delivery performance + AEM content management capabilities
  • The biggest EDS gaps are: multi-step workflow, MSM/live copy (DA), JCR queries, AEM Forms, component inheritance, server-side logic
  • None of the gaps are surprises — they all stem from the fundamental architectural choice: no server-side rendering
  • The hybrid pattern wins for enterprise — EDS for marketing, AEM for application, same domain via CDN routing
  • Evaluate before committing: run through the Architecture Decision Framework with your project's actual requirements before committing to EDS

Series Complete — What Comes Next

You have now completed the EDS series. Here is what you have covered:

ChapterTopic
01What is AEM Edge Delivery Services
02Setting Up Your First EDS Project End to End
03Blocks — The Core Unit of EDS Development
04The EDS Folder Structure — Every File Explained
05Common EDS Issues and How to Debug Them
06EDS Capabilities — What Edge Delivery Can Actually Do
07EDS vs AEM — The Complete Feature Comparison
08Content Storage Architecture — JCR vs EDS Content Bus
09What Is Not Feasible in EDS — And What to Do Instead

If you are an AEM developer building your first EDS project, the recommended reading order is: 1 → 2 → 3 → 7 → 8 → 4 → 5 → 6 → 9

If you are an architect evaluating EDS for a new project: 7 → 9 → 6 → 8 → 1

If you are debugging an existing EDS project: 5 → 3 → 4

The code examples throughout this series come from a real production EDS block library built on aem-boilerplate-xwalk. Every bug in Chapter 5 was a real bug. Every architectural constraint in Chapter 9 was encountered on a real project.

The best way to learn EDS is to build something. Use this series as your reference while you build.

Enjoyed this chapter?

Get an email when I publish the next chapter. No spam — just new technical deep-dives.

Comments

Share feedback or questions about this blog post.

No comments yet. Be the first to share your thoughts.