Most guides to WordPress redirects boil down to “install a plugin and paste two URLs.” That works for one retired post. It breaks when a plugin rule, an .htaccess line, a host setting and WordPress core all try to redirect the same URL, and nobody knows which one answered. The short answer: use a permanent 301 to the closest equivalent page; put one-off redirects in a plugin and pattern-based or migration redirects at the server or host; and know that the first layer to match a request wins. This guide covers each option, the status code to pick, a worked permalink-change example, and how to prove every rule works.
The Short Answer: Where Each Redirect Should Live
Choose the layer by job, not by habit.
| Situation | Best layer | Why |
|---|---|---|
| One retired post or page, editor-managed | Redirection plugin or your SEO plugin’s redirect manager | No server access needed, hit logging, easy to undo |
| Changed slug on an existing post | Nothing, at first: WordPress core handles it | Core issues a 301 from the old slug, but check it |
| Permalink structure change, category flattening | One pattern rule in .htaccess, nginx or host rules | One regex replaces thousands of single rules |
| HTTP to HTTPS, www to non-www | Server, host or CDN | Must fire before WordPress loads, once, site-wide |
| Managed host with no .htaccess (nginx) | Host dashboard redirect rules, or a plugin | .htaccess is simply ignored there |
| Conditional logic (logged-in users, query strings) | Plugin match conditions or custom PHP | A static map can’t express it |
WordPress Already Redirects More Than You Think
Most loops start when a new rule collides with one of these built-in redirects.
- Old slugs. Change a published post’s slug and core’s
wp_old_slug_redirect()sends visitors from the old URL to the current permalink with a 301. It only covers posts whose slug changed. It does nothing for changed category bases, deleted posts or moved pages. - Canonical redirects.
redirect_canonical()uses a 301 to move legacy?p=123style links to pretty permalinks, applies your trailing-slash setting and normalises www versus non-www against your Site URL. It can be filtered or switched off with theredirect_canonicalfilter. - Attachment pages. Since WordPress 6.4, new installs ship with attachment pages disabled (the
wp_attachment_pages_enabledoption), so attachment URLs redirect to the media file. Sites upgraded from older versions kept attachment pages on. - Your SEO plugin. Yoast SEO Premium creates a redirect automatically when a post’s URL changes and offers a redirect or a 410 when you delete one. The Redirection plugin can watch posts, pages and custom post types for URL changes and auto-create redirects too.
The mistake nobody mentions: run two of those auto-redirect features at once and every slug change makes two rules for the same URL. Pick one owner for automatic redirects and turn the other off.
Why the First Layer Wins (and How That Breaks Things)
A request reaches your site in a fixed order: the CDN (Cloudflare Redirect Rules, if you proxy through it), then the web server or host (.htaccess on Apache, nginx config, host dashboard rules), then WordPress (core, then plugins). The first layer that matches sends the redirect, and the layers behind it never see the request.
That explains the two most common WordPress redirect complaints. “My plugin redirect doesn’t work” usually means a server or CDN rule matched first. “Too many redirects” usually means two layers disagree, for example a CDN forcing HTTPS while WordPress’s Site URL still says HTTP, or a server rule adding a trailing slash that redirect_canonical() then strips. If you hit a loop, the too many redirects guide walks the fix.
A useful clue: WordPress’s wp_redirect() sends an X-Redirect-By header naming the application behind the redirect (the default value is “WordPress”, and plugins can set their own or drop it). If a redirect response has no such header, look at the server, host or CDN first.
Pick the Right Status Code
Google’s documentation on redirects and Google Search treats 301 and 308 as permanent: the target is used as a signal that it should be the canonical URL. A 302, 303 or 307 is temporary, and Google doesn’t treat the target as canonical. Google recommends a server-side permanent redirect whenever possible, a 0-second meta refresh if your platform can’t do that, and JavaScript redirects only as a last resort. For the full comparison, see 301 vs 302 redirects.
- 301 for anything moved for good: changed slugs, merged posts, restructures, HTTPS.
- 302 or 307 for genuinely temporary states: a seasonal page, a short maintenance detour.
- 410 or 404 for content you deleted with no real replacement. Google says it treats all 4xx errors except 429 the same way, so the choice between them is housekeeping, not a ranking lever.
One trap for developers: wp_redirect() defaults to a 302. If a theme or custom plugin calls it without passing 301, a permanent move goes out as temporary.
Option 1: A Redirect Plugin
For most sites, the free Redirection plugin is the most practical home for one-off WordPress redirects. Per its documentation it supports 301, 302, 303, 304, 307 and 308 redirects, plus error responses such as 404 and 410; regex for pattern matches; groups to organise large sets; and match conditions such as login status or referrer. It logs 404s so you can see which dead URLs real visitors hit, and it imports CSV, JSON and .htaccess files, plus data from plugins such as Rank Math, Safe Redirect Manager and Simple 301 Redirects.
A basic setup:
- Install Redirection, go to Tools, then Redirection, and run the setup.
- Turn on URL monitoring so slug changes create redirects (and turn off any duplicate feature in your SEO plugin).
- Add the source URL as a relative path (
/old-post/), the target URL, and keep the code at 301. - Check the 404 log weekly for the first month after any restructure.
If you already run Rank Math or Yoast SEO Premium, their redirect managers do the same job. Rank Math’s Redirections module offers 301, 302 and 307 redirects plus 410 and 451 responses, and a 404 monitor. Use one redirect manager, not two.
The trade-off: plugin redirects run inside WordPress, so each matched request loads PHP before the redirect fires. For thousands of rules on a busy site, move structural patterns to the server.
Option 2: .htaccess on Apache Hosting
On Apache hosting, a 301 redirect in WordPress can live in the .htaccess file in your site root. It fires before WordPress loads. A single-page rule looks like Redirect 301 /old-page/ https://example.com/new-page/, and a pattern rule uses RewriteRule with the [R=301,L] flags.
Placement matters. WordPress writes its own block between # BEGIN WordPress and # END WordPress, and its inline note says changes between those markers “will be overwritten.” Put your rules above that block, keep a copy of the original file, and test on staging, because a typo can take the whole site down with a 500 error. The 301 Redirect Generator turns old and new URL pairs into Apache or nginx rules, and the .htaccess Generator builds the HTTPS and canonical-host rules safely. For the wider file, see .htaccess for SEO.
Option 3: Nginx, Managed Hosts and Your CDN
Nginx does not read .htaccess, so rules pasted there do nothing. Several managed WordPress hosts fall into this group:
- WP Engine has deprecated .htaccess. Redirects are managed in its User Portal, where rules are read top to bottom. WP Engine calls roughly 1,000 redirects a soft limit and now points bulk imports to the Rewrite Rules tab of its Web Rules page.
- Kinsta runs nginx, so sites have no .htaccess file. Redirects go in the Redirects tool in MyKinsta, and custom nginx rules are added by its support team.
- Self-managed nginx uses
return 301inside alocationblock, or amapfor long lists.
If the site is proxied through Cloudflare, its Redirect Rules (single, dynamic) and Bulk Redirects (large static lists) run before the request reaches your server. They are the right place for domain-level moves. They are also the first place to check when a WordPress redirect seems to be ignored.
Option 4: Redirects in Code
Custom PHP is for logic a static map can’t express, such as redirecting by a query parameter or user role. Use wp_safe_redirect() when the destination could come from user input, because it only allows hosts your site trusts and so prevents open redirects. Always pass the status code explicitly and call exit; afterwards, since wp_redirect() does not stop execution on its own. Keep it in a must-use plugin, not a theme, so a theme switch doesn’t delete your redirects.
Worked Example: Dropping Dates From Your Permalinks
Say a blog moves from /%year%/%monthnum%/%postname%/ to /%postname%/. Here is the sequence that holds up.
- Snapshot first. Crawl the site and export every live URL, plus the top landing pages from Search Console. This is your redirect map baseline (the redirect mapping guide covers the spreadsheet).
- Change the permalink setting in Settings, then Permalinks.
- Add one pattern rule at the server, for example
RewriteRule ^[0-9]{4}/[0-9]{2}/(.+)$ /$1 [R=301,L]above the WordPress block, withRewriteEngine Onbefore it. - Test the edge cases. This is where most migrations leak. That pattern also catches date-archive pagination such as
/2024/05/page/2/and sends it to/page/2/, which is not the same page. Decide what archives should do, and write those rules first. - Update internal links so menus and in-content links point straight at the new URLs. Google’s site move guidance says to update your own links and keep redirects “for as long as possible,” generally at least a year.
Two rules apply to every map. Redirect each old URL straight to its final destination: Google’s crawlers follow up to 10 hops, but Google advises going to the final URL directly. And don’t send many unrelated URLs to the homepage, because Google may treat that as a soft 404.
Test Every Rule, Then Watch the Data
Spot-check single URLs with curl -sIL https://example.com/old-post/. You want one 301, a location header pointing at the final URL, and a 200 at the end. Two hops means a chain. A 302 means the wrong code. A 404 at the end means a broken target. The check redirects guide covers browser and bulk methods.
At migration scale, spot checks miss things, so crawl the whole list. SEO Rocket’s technical audit runs a real Screaming Frog-backed crawler over your live site and flags redirect chains, broken links and soft-404 candidates. You can fix the map before Google recrawls it, then follow up on any chains with the redirect chains fix list. After launch, the Search Console integration and rank tracking show whether the old URLs’ traffic moved to the new ones or just disappeared. That workflow is the core of a playbook proven across 1,000,000+ ranking pages.
WordPress Redirects FAQ
Do I need a plugin for WordPress redirects?
No. Core already handles changed slugs, and server, host or CDN rules can handle the rest. A plugin is the easiest way for non-developers to manage one-off redirects and see 404 logs, which is why most sites use one.
Do 301 redirects in WordPress lose rankings?
A permanent redirect to a relevant equivalent page is Google’s recommended way to move a URL, and the target becomes the canonical signal. Losses usually come from mistakes: 302s used for permanent moves, chains, redirects to irrelevant pages, or old URLs left as 404s. For plugin-specific fixes, see WP 301 redirects.
How long should I keep redirects?
Google’s site-move guidance says at least a year, and longer while old URLs still get traffic or backlinks. There is little reason to delete a working 301.
Why is my redirect being ignored?
A layer earlier in the request matched first: a CDN rule, a host dashboard rule or an .htaccess line. On nginx hosts, .htaccess rules are never read at all.
The Bottom Line
Good WordPress redirects come down to three decisions: the right code (301 for anything permanent), the right layer (plugin for one-offs, server, host or CDN for patterns and site-wide moves), and one owner per job so rules don’t fight. Map before you change anything, redirect straight to the final URL, test the edge cases your regex catches, and crawl the result. The redirect protects the rankings you’ve earned. Keeping the destination page worth ranking is still your job.