.htaccess 301 Redirects: The Rules You Actually Need After a Site Migration
The handful of .htaccess redirect rules that cover most site migrations, the ordering that keeps them from fighting, and the mistakes that quietly cost rankings.
A new site goes live, the design is better, and two weeks later organic enquiries drop. The usual cause is not the design. It is that every old URL Google knew about now returns a 404, or bounces through three redirects before landing somewhere vaguely related.
If your site runs on Apache, or on LiteSpeed (common on shared hosting, and it reads most of the same rules), the fix lives in one file: .htaccess in the site root. You need far fewer rules than most migration guides suggest. Here are the ones that matter, followed by the order to put them in.
Rule 1: one canonical host, one hop
Pick one version of your domain (HTTPS, with or without www) and send everything else to it in a single redirect. The common mistake is two separate rules: one for HTTP to HTTPS, then another for non-www to www. A visitor on http://example.com then takes two hops instead of one.
RewriteEngine On
# Send HTTP and www traffic to https://example.com in one hop
RewriteCond %{HTTPS} off [OR]
RewriteCond %{HTTP_HOST} ^www\. [NC]
RewriteRule ^ https://example.com%{REQUEST_URI} [R=301,L,NE]
NE stops Apache from re-encoding characters that are already encoded in the path. If you prefer the www version, swap the host condition and target.
One warning if the site sits behind Cloudflare or another proxy: %{HTTPS} may read off even for secure visitors, because the proxy talks to your server over plain HTTP. That produces a redirect loop. Test with the proxy on before trusting this rule.
Rule 2: map old URLs to their real equivalents
This is the part that protects rankings. Export every URL the old site had (from the old sitemap, Google Search Console, and your analytics landing pages) and match each one to the most relevant new page. Not the homepage. Google tends to treat a blanket redirect to the homepage much like a missing page.
For one-to-one moves, RewriteRule with an exact pattern is clearest:
# Old page to new page, exact match only
RewriteRule ^services/crm-setup/?$ /crm-implementation-and-optimization/ [R=301,L]
RewriteRule ^about-us\.html$ /about/ [R=301,L]
Two details trip people up here. In .htaccess, the pattern is matched without the leading slash, so ^/services/ will never match. And [R] on its own sends a 302, not a 301. Apache’s documentation states 302 is the default when no code is given. Always write R=301 explicitly.
Why not the shorter Redirect 301 /old /new syntax? It works, but it matches by path prefix. Redirect 301 /blog /insights also catches /blog/any-post and appends the rest of the path, which may or may not be what you want. Mixing Redirect and RewriteRule in the same file also makes the processing order hard to reason about, since they belong to different Apache modules. Pick RewriteRule and use it throughout.
Rule 3: whole sections that moved together
When a folder was renamed and the slugs stayed the same, one pattern covers hundreds of pages:
# /blog/my-post/ becomes /insights/my-post/
RewriteRule ^blog/(.+)$ /insights/$1 [R=301,L]
Only do this when the slugs genuinely match. If half the old posts were merged or deleted, list those individually above this rule so they get a proper destination first. Specific rules go above general ones, always.
Rule 4: old query string URLs
Older CMS platforms often used URLs like /index.php?page_id=42. A RewriteRule pattern never sees the query string, so you match it with a condition instead:
RewriteCond %{QUERY_STRING} (^|&)page_id=42(&|$)
RewriteRule ^index\.php$ /web-systems/? [R=301,L]
# Apache 2.4 alternative: QSD discards the old query string
RewriteCond %{QUERY_STRING} (^|&)p=118(&|$)
RewriteRule ^$ /insights/some-post/ [R=301,L,QSD]
By default, RewriteRule copies the original query string onto the target. The trailing ? in the first rule, or the QSD flag in the second, prevents ?page_id=42 following the visitor to the new page.
The order that keeps rules from fighting
Put the blocks in this sequence:
| Position | Block | Why here |
|---|---|---|
| 1 | RewriteEngine On |
Nothing below works without it |
| 2 | Query string redirects | Most specific matches |
| 3 | Individual page redirects | Specific paths before patterns |
| 4 | Section patterns | Catch whatever the lists missed |
| 5 | Canonical host and HTTPS | Applies to everything else |
| 6 | CMS or framework rules | Front controller rules belong last |
One catch with relative targets like /web-systems/ in positions 2 to 4: if the visitor arrived on http://www, they get a second hop through the canonical rule. On a large migration, write absolute targets with the final host to keep every old URL at one hop. Google’s crawlers follow up to 10 redirect hops, but each extra hop is wasted crawl time and one more place for something to break.
Test with 302 first
Browsers cache 301 responses hard. If you ship a wrong 301, your own browser may keep sending you to the wrong page long after you fix the file, which makes debugging miserable. Write the rules with R=302, test, then switch to R=301 once everything checks out.
Testing from the command line is faster than clicking around:
# Shows each hop and its status code
curl -sIL http://www.example.com/services/crm-setup | grep -iE "^(HTTP|location)"
For a full migration, put the old URL list in a file and loop through it, flagging anything that does not end in a single 301 followed by a 200.
How long to keep them
Google’s John Mueller has said to keep redirects in place for at least a year, because Google needs to see a redirect several times before it fully moves the signals across. In practice, leave them indefinitely. Old links in emails, PDFs and other people’s websites never stop being clicked, and a few hundred lines of .htaccess cost nothing to keep.
If you are planning a migration and want the redirect map, the server rules and the testing done properly before launch day, that is part of how we build web systems at TOSS, and it is the kind of groundwork our scalable digital foundations work covers. Send us the old and new site details through get a quote and we will tell you what the migration needs.