Skip to main content

Dispatcher & Caching

The Dispatcher is a caching and load-balancing layer that sits in front of AEM Publish instances. It is the first line of defense for performance and security. In AEMaaCS, the Dispatcher runs on Apache HTTP Server with a custom module.

Architecture

In AEMaaCS, the flow is:

  1. Adobe-managed CDN -- first cache layer
  2. Dispatcher -- Apache + Dispatcher module. Second cache layer
  3. AEM Publish -- renders the page if not cached

Most requests should be served from CDN or Dispatcher cache, never reaching Publish.

What the Dispatcher does

FunctionDescription
CachingStores rendered HTML, images, CSS, JS on disk
FilteringBlocks malicious or unnecessary requests
Load balancingDistributes requests across Publish instances
URL rewritingMaps vanity URLs and redirects
SecurityBlocks access to sensitive paths

Dispatcher configuration in your project

The Dispatcher config lives in the dispatcher/ module:

dispatcher/
└── src/
├── conf.d/
│ ├── available_vhosts/
│ │ └── default.vhost # Virtual host configuration
│ ├── enabled_vhosts/
│ │ └── default.vhost -> ... # Symlink to enable
│ ├── rewrites/
│ │ └── rewrite.rules # URL rewrite rules
│ └── variables/
│ └── custom.vars # Custom variables
└── conf.dispatcher.d/
├── available_farms/
│ └── default.farm # Farm configuration
├── enabled_farms/
│ └── default.farm -> ... # Symlink to enable
├── cache/
│ └── rules.any # Cache rules
├── clientheaders/
│ └── clientheaders.any # Forwarded headers
├── filters/
│ └── filters.any # Request filters
└── renders/
└── default_renders.any # Publish instance addresses

Cache rules

Cache rules define which responses the Dispatcher stores:

# cache/rules.any

# Cache HTML pages
/0000 { /type "allow" /glob "*.html" }

# Cache clientlibs (CSS, JS)
/0001 { /type "allow" /glob "/etc.clientlibs/*" }

# Cache static assets
/0002 { /type "allow" /glob "*.css" }
/0003 { /type "allow" /glob "*.js" }
/0004 { /type "allow" /glob "*.gif" }
/0005 { /type "allow" /glob "*.ico" }
/0006 { /type "allow" /glob "*.jpg" }
/0007 { /type "allow" /glob "*.jpeg" }
/0008 { /type "allow" /glob "*.png" }
/0009 { /type "allow" /glob "*.svg" }
/0010 { /type "allow" /glob "*.webp" }
/0011 { /type "allow" /glob "*.woff2" }

# Do not cache JSON API responses (dynamic)
/0100 { /type "deny" /glob "*.json" }

# Exception: cache persisted GraphQL query responses
/0101 { /type "allow" /glob "/graphql/execute.json/*" }

Tip: In AEMaaCS, the default rules are already good. Customize only when needed. Note that the blanket JSON deny above would also block caching of GraphQL persisted query responses. If you use headless delivery (chapter 11), add an explicit allow rule for the persisted query path as shown.

Cacheable responses

The Dispatcher only caches responses that:

  1. Return HTTP 200
  2. Are GET requests (never POST)
  3. Do not have Set-Cookie headers
  4. Do not have Authorization headers
  5. Match the cache rules (/cache section)

Filters

Filters control which requests reach AEM:

# filters/filters.any

# Start from deny-by-default and allow only what is required
/0000 { /type "deny" /url "*" }

# Allow basic delivery paths
/0001 { /type "allow" /method "GET" /url "/content/*" }
/0002 { /type "allow" /method "GET" /url "/etc.clientlibs/*" }

# Allow GraphQL persisted queries
/0010 { /type "allow" /method "GET" /url "/graphql/execute.json/*" }

# Block sensitive paths explicitly
/0100 { /type "deny" /url "/system/*" }
/0101 { /type "deny" /url "/crx/*" }
/0102 { /type "deny" /url "/bin/*" }
/0103 { /type "deny" /url "*.infinity.json" }
/0104 { /type "deny" /url "*.tidy.json" }
/0105 { /type "deny" /url "*.sysview.xml" }
/0106 { /type "deny" /url "*.docview.xml" }
/0107 { /type "deny" /url "*.query.json" }

# Block selectors that expose raw content
/0200 { /type "deny" /selectors '(feed|rss|pages|languages|blueprint|infinity)' }

Filter order matters

Filters are evaluated top to bottom. The last matching filter wins. A common pattern:

  1. Deny all baseline
  2. Allow only explicit delivery paths
  3. Deny sensitive selectors/paths explicitly

Security: Always deny access to /crx/*, /system/console/*, and other admin paths on Publish.

URL rewrites

Rewrite rules map vanity URLs and handle redirects:

# rewrites/rewrite.rules

# Remove /content/mysite/en prefix for clean URLs
RewriteRule ^/content/mysite/en/(.*)$ /$1 [PT,L]

# Redirect www to non-www
RewriteCond %{HTTP_HOST} ^www\.mysite\.com$
RewriteRule ^(.*)$ https://mysite.com$1 [R=301,L]

# Redirect old URLs
RewriteRule ^/old-page$ /new-page [R=301,L]

Vanity URLs

AEM supports vanity URLs in page properties. An author can set /products as a vanity URL for /content/mysite/en/products-and-services. The Dispatcher resolves these through a vanity URL mapping file.

Cache invalidation

When content is published, the Dispatcher cache must be updated. AEM handles this automatically.

Auto-invalidation

When a page is published, AEM sends an invalidation request to the Dispatcher. The Dispatcher marks the cached file (and potentially related files) as stale:

Stat file invalidation

The Dispatcher uses a .stat file mechanism:

  1. When a page is invalidated, the Dispatcher touches the .stat file in the cache directory
  2. On the next request, the Dispatcher checks if the cached file is older than .stat
  3. If older, the file is re-fetched from Publish
  4. If newer, the cached file is served

Stat file level

The statfileslevel setting controls how broadly invalidation spreads:

LevelBehavior
0One .stat at the root -- all content invalidated on any publish
1.stat per first-level directory -- /en/ and /de/ independent
2.stat per second-level -- /en/blog/ and /en/about/ independent

Higher levels = more granular invalidation = better cache hit ratio.

# In the farm config
/statfileslevel "2"

Local Dispatcher testing with the SDK

The AEMaaCS SDK includes a Dispatcher SDK for local testing.

Setup

  1. Download the Dispatcher SDK from the Software Distribution portal
  2. Extract it alongside your AEM SDK
  3. The SDK includes Docker-based tools for running the Dispatcher locally

Validate configuration

# From the dispatcher SDK directory
./bin/validator full dispatcher/src

This validates your Dispatcher configuration against AEMaaCS rules. Common checks:

  • No deprecated directives
  • No hardcoded IPs
  • All includes resolve
  • Filters follow security best practices

Run locally

# Start the local Dispatcher (Docker required)
./bin/docker_run.sh dispatcher/src host.docker.internal:4503

This starts an Apache + Dispatcher instance pointing to your local Publish on port 4503. Test at http://localhost:8080.

AEMaaCS Dispatcher restrictions

In AEMaaCS, the Dispatcher configuration is partially immutable. Adobe manages the base Apache/Dispatcher configuration, and your project can only customize specific areas:

AllowedNot allowed
Custom virtual hosts in conf.d/available_vhosts/Custom Apache modules (LoadModule)
Rewrite rules in conf.d/rewrites/Modifying httpd.conf or dispatcher.any directly
Custom filters in conf.dispatcher.d/filters/Changing the render address (managed by Adobe)
Cache rules in conf.dispatcher.d/cache/Adding AllowOverride or .htaccess files
Custom variables in conf.d/variables/Inline PHP, CGI, or other scripting modules
Client headers in conf.dispatcher.d/clientheaders/Directives that conflict with Adobe's base configuration

The Dispatcher SDK validator (./bin/validator full) enforces these restrictions locally. Always validate before pushing to Cloud Manager -- the pipeline will reject invalid configurations.

Testing checklist

TestWhat to verify
Page loadsPages render correctly through the Dispatcher
CachingReload and check the X-Dispatcher response header
FiltersAdmin paths return 403 or 404
RewritesVanity URLs resolve correctly
InvalidationPublish a page and verify the cache is refreshed
Static assetsCSS, JS, images served with proper cache headers

Troubleshooting quick guide

SymptomFirst checkTypical fix
Unexpected 403 via Dispatcherfilters.any order and last-match behaviorAdd explicit allow for required path before deny selectors
Cache never hitsResponse headers and cache rulesRemove non-cacheable headers where appropriate, adjust rules
Content stale after publishInvalidation logs and statfileslevelVerify flush agent flow and tune invalidation granularity
Vanity URL failsRewrite/vanity mappings and vhostRebuild mappings and validate rewrite conditions
Works direct publish, fails on CDNCDN cache/headers and dispatcher responseAlign cache headers and purge strategy

For detailed configuration, see the Dispatcher Configuration reference. See also Performance for broader optimization strategies and Security Basics for hardening your Publish tier.

Summary

You learned:

  • Dispatcher architecture -- CDN > Dispatcher > Publish
  • Cache rules -- what gets cached and what does not
  • Filters -- blocking malicious requests, allowing legitimate ones
  • URL rewrites -- vanity URLs and redirects
  • Cache invalidation -- stat files, auto-invalidation on publish
  • Stat file level -- controlling invalidation granularity
  • Local testing with the Dispatcher SDK

Next up: Deployment & Cloud Manager -- Git repo structure, Cloud Manager pipelines, environments, content transfer, and Rapid Development Environments.