{"id":77663,"date":"2026-02-12T11:29:07","date_gmt":"2026-02-12T05:59:07","guid":{"rendered":"https:\/\/www.tothenew.com\/blog\/?p=77663"},"modified":"2026-02-13T14:46:50","modified_gmt":"2026-02-13T09:16:50","slug":"manage-large-scale-redirects-in-aem-as-a-cloud-service","status":"publish","type":"post","link":"https:\/\/www.tothenew.com\/blog\/manage-large-scale-redirects-in-aem-as-a-cloud-service\/","title":{"rendered":"Manage Large Scale Redirects in AEM as a Cloud Service"},"content":{"rendered":"<h2>Problem Statement<\/h2>\n<p>We were migrating an old Salesforce-style knowledge base (URLs like <code>\/apex\/ArticleDetails?<\/code>) into AEM as a Cloud Service. Everything looked fine\u2026 until the business came back with a hard requirement:<\/p>\n<p><strong>\u201cWe have ~300 legacy article links still floating around. None of them can break. Fix it.\u201d<\/strong><\/p>\n<p>That immediately pointed to one place: <strong>dispatcher rewrite rules<\/strong>.<\/p>\n<p>And if you&#8217;ve worked with Apache + AEMaaCS dispatcher, you already know it&#8217;s not as simple as dropping a few <code>RewriteRule<\/code> lines and calling it done.<\/p>\n<hr \/>\n<h2>First Attempt (and why it failed)<\/h2>\n<p>The naive approach looks like this:<\/p>\n<pre><code>RewriteCond %{REQUEST_URI} =\/apex\/ArticleDetails [NC]\r\nRewriteCond %{QUERY_STRING} (^|&amp;)article=WaysToOpenAnAccount(&amp;|$) [NC]\r\nRewriteRule ^ \/content\/data-centre\/us\/en\/home\/our-products\/current-accounts\/online-bank-account-opening.article.html [R=301,L,QSD]<\/code><\/pre>\n<p>It works\u2026 for a couple of redirects.<\/p>\n<p>But for <strong>300<\/strong> entries?<\/p>\n<p>* Maintaining hundreds of hardcoded rules becomes painful.<br \/>\n* Every new redirect requires a dispatcher redeploy.<br \/>\n* Business teams can&#8217;t manage it without engineering help.<\/p>\n<p>That wasn&#8217;t going to scale.<\/p>\n<hr \/>\n<h2>Solution<\/h2>\n<p>Use <strong>RewriteMap<\/strong>.<\/p>\n<p>Instead of writing hundreds of conditional rewrite rules, keep a lookup file and let Apache resolve redirects based on the article slug.<\/p>\n<hr \/>\n<h2>Local Setup<\/h2>\n<p>Here&#8217;s what the local setup looked like:<\/p>\n<pre><code>RewriteMap articles dbm=sdbm:\/tmp\/rewrites\/articles.map\r\n\r\nRewriteCond %{REQUEST_URI} ^\/apex\/(s\/)?ArticleDetails$ [NC]\r\nRewriteCond %{QUERY_STRING} (^|&amp;)article=([^&amp;]+)(&amp;|$)\r\nRewriteCond ${articles:%2|NOT_FOUND} !NOT_FOUND\r\n\r\nRewriteRule ^ ${articles:%2}.article.html [R=301,L,QSD]<\/code><\/pre>\n<p>What&#8217;s happening here:<\/p>\n<p>* Apache extracts the value of <code>article=<\/code> from the query string.<br \/>\n* It checks that value in the <code>articles<\/code> map.<br \/>\n* If it finds a match, it redirects.<br \/>\n* If it doesn&#8217;t, the request continues normally.<\/p>\n<p>So the dispatcher config stays clean, and the redirect list lives outside the rewrite logic.<\/p>\n<hr \/>\n<h2>Making It Work in AEM as a Cloud Service<\/h2>\n<p>Local dev was straightforward: I used <code>httxt2dbm<\/code> to convert a text file into DBM format and mounted it under <code>\/tmp\/rewrites<\/code>.<\/p>\n<p>On AEMaaCS, that approach doesn&#8217;t work because you can&#8217;t SSH into dispatcher instances and drop files wherever you want. That&#8217;s where <strong>managed rewrite maps<\/strong> become extremely useful.<\/p>\n<h3>Step 1: Create a DAM asset for the redirect list<\/h3>\n<p>Create a text file in DAM:<\/p>\n<pre><code>\/content\/dam\/redirectmaps\/articles.txt<\/code><\/pre>\n<p>The format is simple: one mapping per line.<\/p>\n<pre><code>WaysToOpenAnAccount our-products\/current-accounts\/online-bank-account-opening\r\nUpdateDebitCardPIN  our-products\/debit-cards\/how-to-update-pin<\/code><\/pre>\n<p>(Keep it consistent: <code>slug destination-path-without-extension<\/code>.)<\/p>\n<h3>Step 2: Add managed rewrite map config in dispatcher repo<\/h3>\n<p>Add the config file here:<\/p>\n<pre><code>dispatcher\/src\/opt-in\/managed-rewrite-maps.yaml<\/code><\/pre>\n<p>And include something like:<\/p>\n<pre><code>maps:\r\n  - name: articles.map\r\n    path: \/content\/dam\/redirectmaps\/articles.txt\r\n    ttl: 300\r\n    wait: true<\/code><\/pre>\n<p>What happens next is the best part:<\/p>\n<p>* AEMaaCS fetches the DAM text file from Publish.<br \/>\n* It converts the file into DBM format.<br \/>\n* It places the generated DBM under <code>\/tmp\/rewrites\/articles.map<\/code> on each dispatcher.<br \/>\n* Your <code>RewriteMap<\/code> directive now has a real file to read from.<\/p>\n<p>So if you want to add a new redirect tomorrow, you don&#8217;t touch dispatcher code. You just update the DAM file, publish it, and within a few minutes (based on <code>ttl<\/code>) the dispatcher picks it up.<\/p>\n<p>No pipeline run, no redeploy, no downtime.<\/p>\n<hr \/>\n<h2>Point to Remember<\/h2>\n<p><strong>Make sure the <code>articles.txt<\/code> asset is published to the Publish\/Preview environment before deployment<\/strong> (or ship it as part of your initial rollout strategy).<br \/>\nIf dispatcher can&#8217;t fetch the DAM asset, the map won&#8217;t build and redirects won&#8217;t resolve.<\/p>\n<hr \/>\n<h2>Lessons Learned<\/h2>\n<ol>\n<li>Don&#8217;t hardcode 300 rewrite rules. Use a <strong>RewriteMap<\/strong>.<\/li>\n<li>Local Docker: build DBM using <code>httxt2dbm<\/code> and mount under <code>\/tmp\/rewrites<\/code>.<\/li>\n<li>Cloud: store redirect list in <strong>DAM<\/strong> + configure <strong>managed-rewrite-maps.yaml<\/strong>. Let AEMaaCS generate the DBM on dispatcher.<\/li>\n<li>Use <code>[QSD]<\/code> (Apache 2.4.65+) to drop the old query string cleanly after redirect.<\/li>\n<\/ol>\n<hr \/>\n<h2>Final Thought<\/h2>\n<p>This started as a panic moment (\u201coh no, 300 redirects\u201d) and ended up becoming a solid pattern.<\/p>\n<p>Now redirect maintenance is just a DAM update\u2014something even non-dev teams can handle\u2014while dispatcher rules stay stable and predictable. Sometimes the best fix isn&#8217;t writing more config. It&#8217;s using the platform feature that was built for exactly this problem.<\/p>\n<hr \/>\n<h3>Reference<\/h3>\n<p><a href=\"https:\/\/experienceleague.adobe.com\/en\/docs\/experience-manager-cloud-service\/content\/implementing\/content-delivery\/pipeline-free-url-redirects\"><br \/>\nhttps:\/\/experienceleague.adobe.com\/en\/docs\/experience-manager-cloud-service\/content\/implementing\/content-delivery\/pipeline-free-url-redirects<br \/>\n<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Problem Statement We were migrating an old Salesforce-style knowledge base (URLs like \/apex\/ArticleDetails?) into AEM as a Cloud Service. Everything looked fine\u2026 until the business came back with a hard requirement: \u201cWe have ~300 legacy article links still floating around. None of them can break. Fix it.\u201d That immediately pointed to one place: dispatcher rewrite [&hellip;]<\/p>\n","protected":false},"author":1745,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"iawp_total_views":56},"categories":[5868],"tags":[5314,4847,5008,1233],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/77663"}],"collection":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/users\/1745"}],"replies":[{"embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/comments?post=77663"}],"version-history":[{"count":5,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/77663\/revisions"}],"predecessor-version":[{"id":77670,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/77663\/revisions\/77670"}],"wp:attachment":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/media?parent=77663"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/categories?post=77663"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/tags?post=77663"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}