You already know 301 means permanent and 302 means temporary. You've migrated domains, shuffled URL structures, and debugged redirect loops. This guide skips the introductions and focuses on optimization strategies, edge cases, and architectural decisions that separate competent redirect implementations from fast, resilient, SEO-friendly ones.
Why Redirect Choice Still Matters in 2026
The fundamental HTTP semantics haven't changed, but the environments where redirects operate have evolved. HTTP/2 and HTTP/3 connection multiplexing, aggressive CDN caching, Core Web Vitals pressure, and crawl budget constraints make redirect efficiency more critical than ever.
A single redirect adds latency—typically 50-200ms depending on geographic distance and connection quality. Multiply that by thousands of requests per hour, and poor redirect architecture becomes a measurable performance and revenue problem. Search engines also interpret redirect signals differently depending on implementation details most guides ignore.
The Caching Paradox: When 302 Caches Like 301
Browsers and CDNs cache 301 redirects aggressively by default. That's the expected behavior. What catches developers off guard is that 302 redirects often cache too—just with different heuristics.
Modern Browser Behavior
Chromium-based browsers will cache 302 redirects for the duration of the browser session unless explicitly told otherwise via Cache-Control headers. Firefox uses similar heuristics. This means a "temporary" redirect can persist in client caches far longer than intended if you don't set explicit cache directives.
To prevent 302 caching:
Header set Cache-Control "no-store, no-cache, must-revalidate, max-age=0"
Header set Pragma "no-cache"
For nginx:
add_header Cache-Control "no-store, no-cache, must-revalidate, max-age=0";
add_header Pragma "no-cache";
Without these headers, your "temporary" redirect becomes semi-permanent in practice, defeating the purpose of using 302 in the first place.
CDN Layer Complications
Cloudflare, Fastly, and other CDNs respect Cache-Control headers but apply their own default caching rules when headers are absent. Cloudflare caches 301 redirects for one hour by default and will cache 302 redirects if you've enabled caching for the response code in your Page Rules or Cache Rules.
If you need a truly ephemeral redirect for A/B testing or canary deployments, verify your CDN configuration explicitly blocks 302 caching. For Cloudflare, check your Cache Rules and ensure 302 is not in the cached status code list.
Redirect Chains: The Hidden Performance Killer
Every hop in a redirect chain multiplies latency and increases failure surface area. Yet redirect chains accumulate organically over time through incremental migrations, CDN rewrites, and legacy rules.
Detection Strategy
Audit your critical paths with curl's redirect-following flag:
curl -sIL -w "\nTotal redirects: %{num_redirects}\nTotal time: %{time_total}s\n" https://example.com/old-page
If num_redirects is greater than 1, you have a chain. For bulk analysis, script this across your top landing pages from analytics.
Common Chain Patterns
Typical chain: HTTP → HTTPS → www → final destination. Four round trips for what should be one.
Optimized approach: Configure your web server or load balancer to perform all transformations in a single redirect. In nginx:
server {
listen 80;
listen 443 ssl;
server_name example.com;
if ($scheme = http) {
return 301 https://www.example.com$request_uri;
}
return 301 https://www.example.com$request_uri;
}
server {
listen 443 ssl http2;
server_name www.example.com;
# actual site config
}
For Apache with mod_rewrite:
RewriteEngine On
RewriteCond %{HTTPS} off [OR]
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^(.*)$ https://www.example.com/$1 [R=301,L]
The key is consolidating conditions so a single redirect handles all canonicalization.
Regex Performance in Rewrite Rules
Complex regex patterns in Apache's mod_rewrite or nginx rewrite blocks execute on every request that matches the context. Poorly optimized patterns create CPU hotspots at scale.
Benchmarking Regex Overhead
Test your patterns outside the web server first:
echo "/category/old-slug-12345" | grep -P '^/category/old-slug-[0-9]+$'
Use PCRE regex with anchors (^ and $) to minimize backtracking. Avoid nested quantifiers and catastrophic backtracking patterns.
Optimization Techniques
Replace regex with simple string matching where possible. Nginx's location directive with exact match (=) or prefix match (^~) is faster than regex:
location = /old-page {
return 301 /new-page;
}
Is significantly faster than:
location ~ ^/old-page$ {
rewrite ^/old-page$ /new-page permanent;
}
For bulk redirects, consider moving the mapping into an external hash table or key-value store like Redis. Load the redirect map into memory and perform lookups via Lua (OpenResty) or a FastCGI script. This trades configuration complexity for runtime performance when managing thousands of individual redirects.
The 308 and 307 Alternative
HTTP 308 (Permanent Redirect) and 307 (Temporary Redirect) are the modern equivalents of 301 and 302 with one critical difference: they guarantee the HTTP method is preserved.
With 301 and 302, browsers historically changed POST requests to GET when following the redirect. This behavior is codified in HTTP standards but often unexpected. If your application relies on POST data surviving a redirect—like during form submissions or API calls—308 and 307 prevent method mutation.
Practical Application
When redirecting POST API endpoints:
location /api/v1/resource {
return 308 /api/v2/resource;
}
This ensures POST data reaches the new endpoint intact. Most modern clients support 307 and 308, but verify your traffic logs if supporting legacy systems.
SEO Signal Nuances
Search engines treat 301 as a strong signal to transfer page authority and consolidate ranking signals. But 302 behavior is more nuanced than "temporary means no authority transfer."
When 302 Transfers Authority
Google has stated that if a 302 redirect remains in place long enough, they may interpret it as permanent and transfer signals anyway. The threshold is deliberately vague—typically several months—but this makes 302 a risky choice for anything beyond true short-term redirects.
Use 302 only when you genuinely intend to revert: maintenance pages with known restoration times, temporary promotions with end dates, or A/B tests with planned conclusions.
Canonicalization Conflicts
If you have both a 301 redirect and a conflicting canonical tag, search engines must resolve the ambiguity. In practice, the redirect typically wins, but the conflict wastes crawl budget as bots verify both signals. Ensure redirect targets match canonical declarations.
Redirect Loops and Distributed Systems
In distributed environments with multiple layers—CDN, load balancer, application server—redirect loops often emerge from conflicting rules across layers.
Debugging Multi-Layer Loops
Add custom headers at each layer to trace the path:
add_header X-Redirect-Layer "nginx-origin";
At your CDN, add another:
// Cloudflare Worker example
response.headers.set('X-Redirect-Layer', 'cloudflare-edge');
When a loop occurs, the accumulated headers reveal which layer initiated each redirect.
Common Distributed Loop Causes
- CDN performs HTTPS redirect, origin performs same redirect
- Load balancer adds
www, application removes it X-Forwarded-Protoheader misread, triggering infinite HTTPS redirects
Solution: Consolidate canonicalization at the edge (CDN or load balancer) and configure origin servers to trust forwarded headers:
set $redirect_scheme $scheme;
if ($http_x_forwarded_proto) {
set $redirect_scheme $http_x_forwarded_proto;
}
if ($redirect_scheme = "http") {
return 301 https://$host$request_uri;
}
Performance Monitoring
Redirects are invisible to many standard monitoring tools because they're handled before application code executes. Implement specific instrumentation:
Web Server Logs
Parse access logs for redirect status codes:
awk '$9 ~ /^30[12378]$/ {print $7}' access.log | sort | uniq -c | sort -rn | head -20
This reveals your most-hit redirect rules. Optimize the top offenders first.
Real User Monitoring
Browser Navigation Timing API includes redirect timing:
const perfData = performance.getEntriesByType('navigation')[0];
const redirectTime = perfData.redirectEnd - perfData.redirectStart;
if (redirectTime > 0) {
console.log(`Redirect added ${redirectTime}ms latency`);
}
Ship this to your analytics to quantify real-world redirect impact.
Wildcard and Pattern Redirects
When migrating entire sections, wildcard redirects maintain URL structure:
RedirectMatch 301 ^/blog/(.*)$ https://newdomain.com/articles/$1
But beware of unintended matches. The above also captures /blog-archive/, /blogger-tools/, and anything else prefixed with "blog". Use word boundaries or more restrictive patterns:
location ~* ^/blog/([^/]+)$ {
return 301 /articles/$1;
}
HTTP/2 Push and Redirects
HTTP/2 Server Push can't skip redirects—if a resource gets redirected, the pushed resource is wasted bandwidth. Audit your push manifest to ensure pushed resources resolve directly without redirects.
Similarly, Early Hints (HTTP 103) can preconnect to redirect targets, but you're better off fixing the redirect than working around it with Early Hints.
Database-Driven Redirects at Scale
For sites with thousands of dynamic redirects (e-commerce category reorganizations, user-generated content migrations), loading all rules into web server config becomes unmaintainable.
Implement a redirect service:
- Store redirect mappings in a fast key-value store (Redis, Memcached)
- Use a lightweight middleware (Lua in OpenResty, or a FastCGI script) to query on cache miss
- Set a short TTL and refresh from the database periodically
- Fall through to application only if no redirect found
This keeps redirect logic centralized and updateable without web server reloads.
Testing Redirect Configurations
Before deploying redirect changes to production:
# Test specific URLs
curl -I https://example.com/old-path
# Verify redirect target and status code
curl -w "HTTP Code: %{http_code}\nRedirect URL: %{redirect_url}\n" -o /dev/null -s https://example.com/old-path
# Check for chains
curl -sILw "Redirect count: %{num_redirects}\n" https://example.com/old-path
Automate this into pre-deployment CI checks. Maintain a list of critical paths and assert their redirect behavior matches expectations.
Edge Cases and Gotchas
Redirect Fragments
URL fragments (the #section part) are never sent to the server. If you redirect /old#section to /new, the fragment is lost. Browsers do not automatically append fragments after a redirect. If fragment preservation matters, handle it client-side with JavaScript.
Query String Preservation
Most web servers preserve query strings by default, but verify your specific syntax:
Apache's Redirect directive preserves query strings, but RedirectMatch does not automatically. Use QSA flag with RewriteRule:
RewriteRule ^old-path$ /new-path [R=301,L,QSA]
Nginx preserves query strings automatically unless you include a ? in the redirect target.
Mobile-Specific Redirects
Redirecting mobile users to m.example.com is increasingly outdated. Responsive design is standard. If you must maintain separate mobile URLs for legacy reasons, use Vary: User-Agent headers and be aware Google penalizes sites that hide content from Googlebot behind mobile redirects.
Conclusion
Redirects are infrastructure, not afterthoughts. Proper implementation demands understanding the interaction between HTTP semantics, browser behavior, CDN caching, search engine signals, and performance constraints. Audit your redirect chains, optimize your patterns, instrument your latency, and treat each redirect as a deliberate architectural decision. The difference between mediocre and excellent redirect hygiene compounds across thousands of requests into measurable improvements in speed, SEO, and user experience.
