Use a one-line Redirect 301 for simple moves; reach for mod_rewrite only when you need to inspect the host, query string, or another request attribute. The simplest working example looks like this:
Redirect 301 /old-page https://example.com/new-page
Drop that into .htaccess and it works on the next request, no server restart needed, as long as AllowOverride permits it in that directory. If you're just mapping one URL to another, stop there. If you need pattern matching, conditions, or logic based on the visitor's request, that's when mod_rewrite earns its complexity.
- Simple one-to-one move:
Redirect 301 - Pattern, condition, or query-string logic:
RewriteRulewithRewriteCond - Testing a rule you're not sure about: use
302until it's confirmed correct
Key Takeaways
A correct Apache 301 redirect starts with choosing mod_alias for simple moves and mod_rewrite only for conditional logic, then verifying with 302 before committing to 301.
| Point | Details |
|---|---|
| Match the tool to the task | Use Redirect 301 for static moves; reserve mod_rewrite for host, query-string, or pattern-based logic. |
| Test before you commit | Deploy with 302 first since browsers and search engines can cache a 301 for weeks. |
| Watch context-specific syntax | Drop the leading slash in .htaccess patterns; VirtualHost keeps it. |
| Avoid chains and loops | Point directly to the final URL, and constrain regex so the [L] flag can't cause a re-match loop. |
| Verify with the right tools | Pingfloat's Redirect Rule Generator and Response Headers Inspector confirm rules work before you ship them. |
Table of Contents
- How Do You Choose Between Apache Redirect Methods?
- What Are the Most Common Apache Redirect Examples?
- Where Should Redirect Rules Actually Live?
- Why Isn't My Apache Redirect Working?
- What Do the QSA and QSD Flags Actually Do?
- What Should Every Developer Remember About Apache Redirects?
- Build and Verify Redirects Without Guesswork
- Where to Read the Official Apache Documentation
- Frequently Asked Questions
- Sources
How Do You Choose Between Apache Redirect Methods?
Apache gives you two separate modules for redirects, and picking the wrong one is the most common source of confusion in htaccess redirect rules. mod_alias handles the Redirect and RedirectMatch directives. mod_rewrite handles RewriteRule and RewriteCond. They solve overlapping problems but were built for different jobs.

mod_alias is the right call for anything static: a page that moved, a folder that got renamed, a whole domain that needs to point somewhere else while keeping the same path structure. It's lightweight, preserves the request path by default, and does exactly what it says with no surprises. Apache's own documentation is blunt about this: reach for mod_alias before mod_rewrite whenever the redirect is simple, because mod_rewrite carries more processing overhead and more ways to misconfigure it.
mod_rewrite earns its keep when you need to check something beyond the URL path itself. Inspecting the Host header to force a canonical domain, reading a query string, checking a cookie, or matching a complex regex pattern across many URLs at once. That's mod_rewrite territory.
The order-of-execution detail catches people off guard: in server or virtual host context, mod_rewrite rules process before mod_alias. Inside a .htaccess file, that ordering flips, and mod_alias runs first. Mix both modules in the same scope and you can get redirect behavior that contradicts what the file order suggests.
- Static, one-to-one, or prefix redirects: use
mod_alias - Conditional logic, host checks, or query-string manipulation: use
mod_rewrite - Never assume both modules will process rules in the order you wrote them
Pro Tip: Pick one module per file. If a .htaccess file mixes Redirect and RewriteRule directives, debugging becomes a guessing game about which rule fired first. Keep redirect logic in one module and you'll spend far less time troubleshooting.
What Are the Most Common Apache Redirect Examples?
Most real-world redirect needs fall into five patterns. Here's each one, ready to adapt.
- Single page.
Redirect 301 /old-page https://example.com/new-pagemoves one URL to another, keeping full control over the destination. - Folder or subtree.
RedirectMatch 301 ^/blog/(.*)$ https://example.com/articles/$1catches everything under/blog/and remaps it, preserving whatever came after the folder name. Anchor the pattern with^and$or you'll accidentally match partial strings elsewhere on the site. - Domain migration preserving path.
RewriteRule ^(.*)$ https://newdomain.com$1 [R=301,L]sends every request on the old domain to the same path on the new one, which is the version InMotion Hosting's deployment guide recommends for full-site moves. - Force www or non-www, and force HTTPS. For redirecting www to non-www in htaccess:
Flip the condition to redirect non-www to www instead. For HTTP to HTTPS in Apache:RewriteCond %{HTTP_HOST} ^www\.example\.com [NC] RewriteRule ^(.*)$ https://example.com/$1 [R=301,L]RewriteCond %{HTTPS} off RewriteRule ^(.*)$ https://%{http_host}%{request_uri} [R=301,L] - Trailing slash. Apply a trailing-slash rule only when your app treats
/pageand/page/as different resources; otherwise you risk creating a redirect for URLs that already work fine.
Every one of these can run in a virtual host or in .htaccess — placement changes how you write the pattern, which the next section covers.
Where Should Redirect Rules Actually Live?
Server-config and virtual host redirects run once, at server startup, and apply to every request without Apache re-reading a file each time. That's why Apache's own remapping documentation recommends VirtualHost placement for production sites whenever you have access to the server config. A domain-wide HTTPS redirect there looks like this:
<VirtualHost *:80>
ServerName example.com
Redirect 301 / https://example.com/
</VirtualHost>
.htaccess remains the practical choice on shared hosting where you can't touch the main config. The catch that trips up almost everyone moving from VirtualHost to .htaccess: per-directory context strips the directory prefix before matching. A pattern written as ^/old-page in a VirtualHost block needs to become ^old-page (no leading slash) inside .htaccess, because Apache has already removed the directory portion by the time the rule evaluates.
Before assuming a rule is broken, confirm the basics:
- Check that
AllowOverride All(or at leastAllowOverride FileInfo) is set for that directory, otherwise.htaccessrules get silently ignored. - Confirm
mod_rewriteormod_aliasis actually loaded (apachectl -Mon most Linux distributions). - Verify the
.htaccessfile sits in the directory it's supposed to govern, not one level up or down.
Pro Tip: Run curl -I https://example.com/old-page before and after deploying a rule. It shows the raw status code and Location header without any browser cache getting in the way, which is the fastest way to confirm a rule actually fired.
Why Isn't My Apache Redirect Working?
Browsers cache 301 responses aggressively, sometimes for weeks, which means a broken rule can look "fixed" in your browser while still misbehaving for everyone else. Apache's per-directory documentation is explicit about this: test with a 302 first, confirm the destination is correct, and only switch to 301 once you're sure. Search engines cache 301s too, so an incorrect permanent redirect can linger in an index for a long stretch.
Four failure patterns account for most support tickets:
- Redirect chains. Old URL points to a second old URL, which finally points to the real destination. Each hop adds latency and dilutes the signal you're trying to preserve. Point directly at the final destination instead.
- AllowOverride blocking everything. If it's set to
None, your.htaccessrules simply never run, and Apache won't necessarily tell you why. - Module not loaded. A rule referencing
RewriteEngine Ondoes nothing ifmod_rewriteisn't enabled on that server. - Rule order and mixing. As covered earlier,
mod_aliasandmod_rewriteprocess in different orders depending on context, and two rules stacked in the wrong sequence can override each other silently.
Query strings add another wrinkle. Redirect and RedirectMatch carry the original query string along automatically, while RewriteRule does the same by default unless you add flags to change that behavior, covered next.
What Do the QSA and QSD Flags Actually Do?
Inside .htaccess, dropping the leading ^/ from a pattern is non-negotiable, because per-directory context has already stripped it. A rule written as RewriteRule ^/products/(.*)$ ... will simply never match inside .htaccess; it needs to read RewriteRule ^products/(.*)$ ... instead.
The [L] flag stops the current rewrite pass, but it doesn't guarantee the engine won't run again. If your substituted URL still matches the same pattern, Apache can re-enter the rule on the next pass and create a loop. Constrain your regex or add a RewriteCond that excludes the already-rewritten form.
On query strings: RewriteRule passes the original query string through by default. Add QSA to append new parameters onto the existing ones, or QSD to drop the query string entirely, both documented in Apache's mod_rewrite guide.
- Never accept a full URL from user input as a redirect target; validate against an allowlist or restrict to relative paths, or you've built an open-redirect vulnerability.
- Test any rule touching query strings with a URL that actually has parameters attached, not just the bare path.
Pro Tip: If a rewrite rule seems to randomly stop working after a few requests, suspect a loop or a caching layer, not a syntax error, since syntax errors that will actually throw a 500 tend to fail loudly, not intermittently.
What Should Every Developer Remember About Apache Redirects?
Three rules cover nearly every situation you'll run into: pick the simplest directive that solves the problem, always test with a 302 before switching to 301, and never let a redirect chain more than one hop from old URL to new. Most of the debugging pain in Apache redirect work traces back to skipping one of those three.
Beyond the rules, tooling matters. Pingfloat's Redirect Rule Generator builds correct .htaccess or VirtualHost snippets without you having to remember whether a leading slash belongs in the pattern. Pair that with a quick HTTP status code check while testing, since confirming you're actually looking at a 301 and not a cached 200 saves real debugging time.
Build and Verify Redirects Without Guesswork
Writing redirect syntax by hand is where most mistakes creep in: a missing slash, a forgotten L] flag, a RewriteCond that doesn't quite match the intended host. Pingfloat's [Redirect Rule Generator builds correct .htaccess or VirtualHost snippets for single-page moves, domain migrations, and www or HTTPS canonicalization, so you're pasting tested syntax instead of debugging your own typos.

Once a rule is live, verify it the right way. Pingfloat's HTTP Status Codes Reference confirms what each response code actually means, and the Response Headers Inspector shows the exact Location header and cache directives your server is returning, catching cases where a browser's cached 301 is hiding a rule that's actually broken. Run your test in an incognito window, confirm the status with curl -I, then check the headers directly through Pingfloat before you consider the redirect finished.
Where to Read the Official Apache Documentation
- Guide to Apache mod_rewrite
- When not to use mod_rewrite
- Per-directory rewrites (.htaccess)
- Best way to do 301 redirects (ServerFault)
Frequently Asked Questions
What's the difference between a 301 and a 302 redirect in Apache?
A 301 tells browsers and search engines the move is permanent, and they'll cache that response, sometimes for weeks. A 302 signals a temporary move and isn't cached the same way, which is exactly why it's the safer choice while you're still confirming a rule works.
Does .htaccess require a server restart to apply redirect rules?
No. Apache reads .htaccess on every request, so a saved change takes effect on the next page load, as long as AllowOverride permits it for that directory.
Why does my RewriteRule work in VirtualHost but not in .htaccess?
Per-directory context strips the directory prefix before matching, so a pattern written with a leading slash in VirtualHost config needs that slash removed inside .htaccess.
Can I redirect www to non-www and enforce HTTPS in the same file?
Yes. Stack both RewriteCond blocks in the same .htaccess or VirtualHost file, one checking HTTP_HOST for the www prefix and another checking HTTPS status, each followed by its own RewriteRule.

Will a 301 redirect hurt my search rankings? A properly configured single-hop 301 generally preserves the ranking signal associated with the old URL. What actually causes damage is redirect chains, since each extra hop adds latency and increases the chance a crawler gives up before reaching the final destination.
Sources
- Best way to do 301 redirects
- When not to use mod_rewrite (Apache documentation)
- Per-directory Rewrites (Apache HTTP Server 2.4 documentation)
- Guide to Apache mod_rewrite
