Managing Redirects in EmDash
Redirects are the kind of thing you don't think about until you need them urgently. You've changed a URL structure, migrated from WordPress, or renamed a pillar article — and now every inbound link from the last three years is pointing somewhere that returns a 404. Getting redirects right protects your SEO equity and doesn't leave visitors stranded.
EmDash and Cloudflare give you two distinct tools for this. They serve different purposes and scale differently. I'll cover both so you can choose the right one for each situation.
Two Approaches: When to Use Each
EmDash has a built-in _emdash_redirects table managed from the admin panel. Cloudflare offers two options: a _redirects plain-text file deployed with your Pages project, and dynamic Redirect Rules configured in the Cloudflare dashboard. The right choice depends on volume, frequency of change, and whether you need pattern matching.
| Method | Best for | Managed via | Pattern matching |
| EmDash admin redirects | Ongoing CMS-managed redirects, editor-controlled | Admin panel | No |
| Cloudflare _redirects file | One-time migration, up to 2,000 rules | Deployed file (version controlled) | Splats and placeholders |
| Cloudflare Redirect Rules | Complex patterns, regex, header-based, up to 10 on free plan | Cloudflare dashboard | Full regex, Firewall Rules expressions |
EmDash Built-In Redirects
EmDash maintains a _emdash_redirects table in your D1 database. You manage these from the admin panel under Settings > Redirects. Each redirect is a from path, a to path, and a status code (301 permanent or 302 temporary). These are evaluated by the EmDash Worker before content is served.
Use this approach for redirects that editors need to manage without a deploy: changing a page slug, retiring old campaign landing pages, or fixing a permalink that got mangled. The change takes effect immediately — no deploy cycle, no PR.
The limitation is scale: this approach is designed for dozens of redirects, not thousands. It evaluates against every request path, so a very large redirect table adds latency. For bulk migrations, use the Cloudflare _redirects file instead.
A 301 redirect preserves link equity. A 302 does not. If you're migrating old URLs permanently, always use 301 — your search rankings depend on it.
Cloudflare Pages _redirects File
Cloudflare Pages supports a _redirects file in your site's output directory. Place it in your public_html/ folder (or wherever your build output goes) and it gets processed at the edge before your Worker even runs. This makes it extremely fast — Cloudflare handles the redirect without your Worker code executing at all.
# Simple path-to-path redirects (301 permanent)
/old-blog/post-title /learn/new-post-title 301
/wordpress-category/tutorials /category/tutorials 301
# Splat redirect: catch all old /blog/* URLs and map to /learn/*
/blog/* /learn/:splat 301
# Retired pages pointing to the closest relevant content
/pricing / 301
/about-old /pages/about 301
# Temporary redirect (302) -- for time-limited campaigns
/sale /pages/summer-sale 302 The splat syntax (:splat) captures the wildcard portion and places it in the destination. This is the cleanest way to handle a complete URL structure change — /blog/my-post becomes /learn/my-post with one rule. Cloudflare supports up to 2,000 rules in the _redirects file on the free plan.
Cloudflare Redirect Rules for Complex Cases
For redirects that need regex patterns, query parameter matching, or country-based routing, Cloudflare's Redirect Rules in the dashboard give you full flexibility. Navigate to your Cloudflare zone, then Rules > Redirect Rules. The free plan includes 10 dynamic redirect rules.
A common use case is redirecting old query string URLs from a WordPress migration. WordPress often generates URLs like ?p=123 or ?page_id=456. You can write a Redirect Rule that matches http.request.uri.query contains "p=" and redirects to the canonical slug. This is impossible to express cleanly in the _redirects file.
Verifying Redirects
Always test redirects with curl -I rather than a browser. Browsers follow redirects transparently and cache them aggressively. Curl shows you exactly what the server returns: the status code, the Location header, and whether it's a 301 or 302.
# Check the redirect response (don't follow it)
curl -I https://yourdomain.com/old-path
# Expected output for a correct 301:
# HTTP/2 301
# location: https://yourdomain.com/new-path
# Follow the chain to verify the final destination
curl -L -I https://yourdomain.com/old-path