For hundreds of fixed URL moves, the maintainable Nginx design is an http-context map whose entries live in a separate included file. Each old path maps directly to its final destination, and a return 301 sends the redirect. Use rewrite only when a genuine regular-expression pattern can replace many URLs. Validate the configuration with nginx -t, reload through your normal service process, then test both the status code and every Location header.
Need a server to try this on? Antihost offers Linux VPS plans with NVMe storage, full root access and a 14-day free trial.
This approach keeps a large redirect inventory reviewable, gives exact paths predictable precedence, and avoids scattering hundreds of directives through server and location blocks.
As an Amazon Associate I earn from qualifying purchases.
Recommended Free Tools
Use a map and an included file for a large redirect list
An Nginx map is designed to translate one variable into another. It supports exact string keys, masks, regular expressions, a default value, and an include directive for loading entries from another file. Put the map in the http context, then use the resulting variable in the server that receives the legacy requests.
Map variables are evaluated lazily. Declaring a large map does not itself add request-processing work; evaluation occurs when a request uses the mapped variable. That makes an included table practical even when it contains hundreds or thousands of entries.
#1 Best Overall
Base configuration
http {
map $request_uri $redirect_target {
default "";
include /etc/nginx/redirects.map;
}
server {
listen 80;
server_name old.example.com;
if ($redirect_target != "") {
return 301 https://www.example.com$redirect_target;
}
}
}
The map reads the original request URI and stores the selected destination in $redirect_target. The empty default means that an unmapped request is not redirected by this block. The conditional return runs only when a destination was found.
Format the included data file
Each map entry is a key followed by a value and a semicolon. Keep one mapping per line so reviews, diffs, and automated generation remain straightforward.
Crashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minutePC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11/old-product /products/new-product;
/legacy/about https://www.example.com/about;
The first value is a path, so the server block adds the destination host. The second value is already an absolute URL. Choose one convention for your project and document it; mixing conventions is valid, but it makes generation and review easier to get wrong.
Store the table outside the main configuration
Generate /etc/nginx/redirects.map from a reviewed source list rather than hand-editing hundreds of lines in the main file. Make duplicate old paths fail your build or review process. A duplicate key can otherwise hide a mistake, especially when a later edit appears to change a redirect but does not win according to map matching rules.
Choose the correct key and destination format
$request_uri versus $uri
$request_uri contains the original URI, including the original arguments (query string). $uri is Nginx’s normalized URI variable. Select the one that matches the inventory you are importing:
- Use
$request_uriwhen query strings or the original encoded form are part of the mapping decision. - Use
$uriwhen the table is based on normalized paths and query strings should not distinguish entries.
Do not assume that a path-only key covers every query-string case when the map is keyed by $request_uri. Verify the exact requests your old links generate.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Relative paths and absolute URLs
A path value such as /products/new-product is useful when every destination stays on the new host. The server block can prepend https://www.example.com. An absolute value such as https://www.example.com/about is clearer when destinations vary by host or when you want the data file to be self-contained.
Rank #2
If the map value is always a complete destination URL, the server can use a direct return:
map $request_uri $redirect_target {
default "";
include /etc/nginx/redirects.map;
}
server {
listen 80;
server_name old.example.com;
if ($redirect_target != "") {
return 301 $redirect_target;
}
}
Check the URL form and variable usage against the Nginx version running in production before rollout, especially if you change from path values to complete URLs.
Understand matching precedence before adding rules
Nginx evaluates map keys in a defined order. Exact strings are selected before masks, regular expressions are considered in their listed order, and the default value handles everything else. This order determines which destination wins when a specific path also fits a broad pattern.
Do these 3 things before closing this tab:
1Clear out junk files and repair common Windows errors2Fix the driver behind crashes, sound loss and screen glitches3Repair Windows errors before they cause bigger problems| Entry type | Typical use | What to watch |
|---|---|---|
| Exact string | One old URL to one destination | Use for the bulk of a reviewed migration table. |
| Mask or wildcard | A controlled family of names | Confirm it does not unexpectedly capture a more specific path. |
| Regular expression | Patterned transformations | Regex entries are considered in the order written; broad expressions can steal matches. |
default |
Fallback for misses | An empty default is useful when unmapped requests should continue normally. |
Put exact paths in the data set and keep broad expressions below them. If a migration has an exception, represent that exception as an exact entry and test it explicitly.
Use return 301 for fixed mappings
Nginx documents return as the direct mechanism for sending a specific redirect status from server or location context. It is the clearest choice when an old URL has a known final destination.
server {
listen 80;
server_name old.example.com;
location = /old-product {
return 301 https://www.example.com/products/new-product;
}
}
For hundreds of entries, the map keeps those fixed destinations in data rather than repeating inline directives. Use an inline return for a small exception or a special host rule, not as the default way to maintain a large inventory.
Use rewrite only for real patterns
rewrite applies a regular expression and can substitute captured path parts. It is appropriate when many old URLs share a reliable structure, such as moving an entire section while preserving a slug.
server {
listen 80;
server_name old.example.com;
rewrite ^/old-section/(.*)$ https://www.example.com/new-section/$1 permanent;
}
The permanent flag produces a 301 response. Rewrite directives execute sequentially in the order they appear, so ordering is part of the behavior. Place a narrow rule before a broader one, and do not add a regex merely to avoid creating a data file when the redirects are actually one-off mappings.
Why a broad rewrite can be dangerous
A pattern that also matches its own destination can redirect repeatedly. A rule that catches the already-canonical host can create a host loop. Rewrite processing can also repeat location selection; Nginx limits rewrite cycles to 10, and a cycle can end in a 500 error. Treat every regex as code: define its intended input set, its final output, and a test for a URL that must not match.
Keep host migrations in a dedicated server block
When an entire hostname is moving, define a separate server for the old host and return the new host with the original request URI:
server {
listen 80;
server_name example.org;
return 301 http://www.example.org$request_uri;
}
A dedicated old-host server is preferable to conditional rewrite logic. It makes the host boundary explicit and prevents a redirect intended for the legacy hostname from affecting requests already sent to the canonical host.
If the destination should be HTTPS, use the final HTTPS URL in the return. If the migration also changes paths, use a map in the old-host server instead of combining an unconditional host redirect with a second path redirect; that combination commonly creates chains.
Prevent chains, loops, and accidental misses
Point directly to the final URL
A chain such as /a to /b to /c adds requests and makes failures harder to diagnose. Build the table so every legacy URL points directly to /c, the final canonical destination, whenever the final destination is known.
Check slash and case variants
Decide whether /guide and /guide/ are separate inputs in your inventory. Test both if users or old links may send both. Do the same for case differences; do not assume a case variant will match an exact map key.
Rank #4
Check encoding and arguments
Percent-encoded paths can look different from their decoded form, and $request_uri preserves the original request representation. Include encoded examples in testing. Query strings may need to be preserved, discarded, or mapped to a different destination; encode that decision in the table and verify it with an actual request.
Do not redirect the canonical request back to itself
Confirm that the old-host server is not selected for the new host and that a destination URL does not match the conditions that trigger the old rule. A self-targeting rule can loop even when the path mapping itself looks correct.
Roll out the map safely
- Prepare a source list. Keep the old path, intended final URL, and any notes in a reviewable format. Generate the Nginx include file from that source.
- Reject duplicate inputs. Make duplicate old paths fail generation or require an explicit review decision.
- Review high-risk entries. Inspect host changes, encoded paths, trailing-slash variants, query-string behavior, and any regexes separately from ordinary exact mappings.
- Install the include file. Ensure the Nginx worker can read the file and that the path in
includeexactly matches the installed location. - Validate syntax. Run
sudo nginx -t. Do not reload if the test reports an error; the output identifies the configuration file and line that needs correction. - Reload normally. Use your operating system or container’s normal Nginx service-management process. A reload applies the new configuration without treating a syntax failure as a successful deployment.
- Test before broad traffic arrives. Check representative exact hits, misses, host requests, query strings, slash variants, and encoded paths.
- Inspect post-deployment logs. Look for unexpected 3xx chains, 404 responses at destinations, and repeated requests that indicate a loop.
Test status and Location for every URL
A redirect is correct only when both its status and destination are correct. Nginx’s redirect guidance demonstrates checking headers with curl; use the same approach for your migration.
Inspect one response
curl -sS -D - -o /dev/null https://old.example.com/old-product
For a mapped entry, verify a 301 status and a Location header pointing to the intended final URL. The body is irrelevant to this check, so -o /dev/null keeps the output focused on headers.
Follow the chain when diagnosing
curl -sS -I -L https://old.example.com/old-product
Use a follow-redirect request to reveal whether an old URL reaches the final destination through extra hops. A migration table should normally produce one redirect from the old URL to the canonical URL, not a sequence of legacy redirects.
Run a batch check from the reviewed source list
Keep testing data separate from the Nginx syntax file. For a two-column list containing an old path and expected absolute URL, a shell loop can issue one header request per row:
while IFS=' ' read -r old_path expected; do
printf 'n%sn' "$old_path"
curl -sS -D - -o /dev/null "https://old.example.com${old_path}"
done < redirect-test-list.txt
Compare each response’s status and Location with the expected value. Include unmapped paths in the test list to confirm they do not receive an unintended redirect.
Troubleshoot common failures
nginx -t reports an include or syntax error
- Confirm the included file exists at the exact path in the
includedirective. - Check that every map entry ends with a semicolon and that values containing spaces are quoted appropriately.
- Look at the reported line number in both the main configuration and the generated data file.
- Do not reload until the test passes.
The request returns 200 instead of 301
- Confirm the request reached the server whose
server_namematches the old host. - Verify that the map key matches the variable you selected:
$request_uriand$urido not represent the same input in every case. - Check the exact path, trailing slash, case, encoding, and query string.
- Ensure the map’s
defaultis not being mistaken for a destination; an empty default should leave an unmapped request untouched.
The wrong destination wins
Look for a broad mask or regular expression that also matches the request. Exact keys have priority over masks, and regular expressions are considered in their listed order. Move or narrow the expression and add a test for the exception.
The response loops or ends in 500
Use curl -I -L to see each hop. Check whether the destination matches the source rule, whether the canonical host is being caught by the old-host server, and whether multiple rewrite directives send the request back through the same pattern. Nginx stops after 10 rewrite cycles, so a cycle can surface as a 500 response.
Free tools Windows power users keep installed
One-click scans. No signup required.
The redirect has an unexpected query string
Recheck whether the map is keyed by $request_uri, which includes original arguments, or by $uri, which is normalized. Test the exact query-string variants that matter to your application and make the destination value explicit for each required behavior.
Maintain the redirect inventory after launch
Treat the map as a controlled data set, not a permanent dumping ground. Keep the source list under review, regenerate the include file consistently, and preserve a record of why exceptional entries exist. When a destination changes, update the old URL directly to the new final URL instead of adding another intermediate redirect.
After deployment, sample access logs for unexpected 3xx responses, destination 404s, and repeated requests. Remove obsolete mappings only when you have verified that the old URLs no longer need coverage; deleting an entry changes an intentional 301 into whatever behavior the server uses for an unmapped request.
Decision guide: map, return, or rewrite
| Situation | Preferred mechanism | Reason |
|---|---|---|
| Hundreds of unrelated old paths | map plus an included file and return 301 |
Centralizes exact mappings and keeps the main configuration readable. |
| A handful of fixed exceptions | Inline return 301 |
Direct and easy to audit. |
| Many URLs share one proven path pattern | rewrite ... permanent |
Captures and substitutes the changing path portion. |
| Entire hostname migration | Dedicated old-host server with return 301 |
Keeps host handling separate from path logic. |
For the title’s specific case—hundreds of known old URLs—the map-and-include design with direct 301 destinations is the safest default. Reserve regex rewrites for transformations you can describe precisely and test without ambiguity.
The Tool Desk
Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




