Mastering Nginx Rewrite Rules for SEO-Friendly URL Migrations
Learn to implement Nginx rewrite rules and conditional redirects using the map directive. Keep your site's SEO ranking intact during complex migrations.
When we migrated our legacy marketing site to a new structure last year, I initially tried to solve the URL mapping problem with a massive block of if statements inside the Nginx server config. It worked for about ten minutes, but the server load spiked, and I quickly realized that Nginx if is evil. I ended up refactoring the entire logic to use the map directive, which is significantly more performant and easier to maintain.
If you’re managing a migration or trying to clean up legacy URL structures, you need a strategy that doesn't sacrifice your search engine rankings.
Why You Should Avoid Nginx if
In Nginx, the if directive inside a location block can cause unpredictable behavior. It’s infamous for breaking things like try_files or causing unexpected internal redirects. Instead, leverage the map module to create a lookup table.
Think of map as a key-value store that executes before the request is even fully processed. It’s fast, clean, and keeps your server block readable.
Implementing Nginx Conditional Redirects with Map
To handle a migration where you have a list of old URLs that need to point to new ones, define your map outside the http block (usually in your nginx.conf or a dedicated redirects.conf file).
NGINXmap $request_uri $new_uri { default ""; /old-page-1 /new-page-1; /old-page-2 /new-page-2; /blog/old-post /blog/new-post; } server { listen 80; server_name example.com; if ($new_uri) { return 301 $new_uri; } }
This approach is highly scalable. You can have hundreds of mappings, and Nginx will handle them efficiently. If you're coming from a platform like WordPress, this is a much cleaner way to handle redirects than relying solely on the core WordPress Rewrite API: How URL Requests Map to Content, especially when you're moving content off the platform entirely.
Advanced Nginx Rewrite Rules
Sometimes a simple 1:1 map isn't enough. You might need to change URL patterns dynamically—like changing all /category/name structures to /name. For these cases, rewrite is your best friend.
NGINX# Regex-based redirect rewrite ^/category/(.*)$ /$1 permanent;
The permanent flag tells Nginx to send a 301 redirect. If you're testing, use redirect (a 302) first so browsers don't cache the wrong destination while you're debugging.
Comparing Redirection Strategies
| Method | Best For | Performance |
|---|---|---|
map directive | Large lists of URL changes | Excellent |
rewrite | Pattern-based URL changes | Good |
if block | One-off, rare conditions | Poor |
Handling URL Masking
Sometimes you need to serve content from a different source without the user knowing, often called Nginx URL masking. You can use the proxy_pass directive combined with rewrite to keep the user's browser URL static while fetching content from a backend or another microservice.
NGINXlocation /api/ { rewrite ^/api/(.*) /$1 break; proxy_pass http://backend_service; }
The break flag is crucial here; it tells Nginx to stop searching for other rewrite rules in the current location, preventing a loop. If you are dealing with more complex routing logic, it's worth understanding how WordPress URL rewriting: How parse_request maps your site permalinks works, as it helps you identify where your traffic is actually hitting the server before the Nginx layer even sees it.
Avoiding Common Pitfalls
- Don't over-nest: Keep your logic flat. If you find yourself nesting
ifstatements, you're doing it wrong. - Test your regex: Use a tool like Regex101 to verify your patterns before pushing to production.
- Flush your cache: If you're coming from an environment that manages its own rules, like WordPress rewrite rules: How Regex Patterns Generate from Permalinks, ensure you aren't fighting against cached rules in your application layer.
I’m still experimenting with using Lua scripts within Nginx for even more complex, database-driven redirects. It adds a bit of complexity to the build process, but it’s a game-changer for sites with thousands of dynamic redirects. For now, sticking to the map directive has saved me from countless hours of debugging broken redirects.
FAQ
Does using the map directive slow down Nginx?
No, map is evaluated in memory and is extremely fast. It’s significantly more efficient than running multiple regex evaluations within if blocks.
Can I use map for partial URL matches?
Standard map uses exact matches. For partial matches, stick to rewrite with regex, or use a complex map with regex capture groups if you're comfortable with Nginx syntax.
Why shouldn't I use 302 redirects for SEO? 302 redirects are temporary. Search engines won't pass "link juice" (authority) to the new URL. Always use 301 for permanent migrations to ensure your SEO rankings transfer correctly.