Site search

Search IndexLane

Type at least two characters to search.

    Technical note

    How to remove redirect chains from your website

    Trace old URLs to their final destination, fix conflicting server and CDN rules, and check the deployed redirects as well as the redirect map.

    By NikoPublished November 5, 2026Read 5 min

    If /old-product redirects to /shop/old-product, which then redirects to /products/new-name, update both old URLs to point straight to the final page. Each extra hop adds a request and another opportunity for a timeout, loop, or conflicting rule.

    Start with loops, broken destinations, and chains on important landing pages. A few short chains on a small site are rarely the first priority. On a large migration, they can affect thousands of URLs. Google's crawl-efficiency guidance recommends avoiding long chains.

    Record every redirect hop

    Start from more than the current sitemap, which should contain final canonical URLs. Include legacy migration maps, internal-link exports, top external landing pages, analytics history, and redirect-rule sources. Use GET, since some applications handle HEAD differently. Keep every intermediate response, including cross-host redirects and relative Location values.

    A compact Python check can use the redirect history already recorded by requests:

    import requests
    
    def trace_redirect(start_url):
        response = requests.get(start_url, timeout=15, allow_redirects=True)
        hops = [
            {
                'url': item.url,
                'status': item.status_code,
                'location': item.headers.get('Location'),
            }
            for item in response.history
        ]
        hops.append({'url': response.url, 'status': response.status_code})
        return hops
    

    Set a bounded redirect limit, catch loops and network failures, and retain cross-host hops. Any chain with more than one redirect is a candidate for flattening; loops, protocol downgrades, and error endpoints are release blockers.

    Send old URLs directly to the final page

    Change the rules that produce the redirects, whether they are in the application, web server, or CDN. For example, Nginx can send both old paths directly to the final destination:

    # Before (creates a chain):
    # /old-product → /products/old-product → /products/new-name
    
    # After (flattened):
    location = /old-product {
        return 301 /products/new-name;
    }
    
    location = /products/old-product {
        return 301 /products/new-name;
    }
    

    For Go-based sites using net/http:

    package main
    
    import "net/http"
    
    func redirectHandler(w http.ResponseWriter, r *http.Request) {
        // Flattened redirect map
        redirects := map[string]string{
            "/old-product":     "/products/new-name",
            "/products/old-product": "/products/new-name",
            "/blog/post-123":   "/blog/new-post-title",
            "/blog/old-slug":   "/blog/new-post-title",
        }
    
        if target, ok := redirects[r.URL.Path]; ok {
            http.Redirect(w, r, target, http.StatusMovedPermanently)
            return
        }
    
        http.NotFound(w, r)
    }
    

    Check WordPress and plugin rules

    WordPress redirects can come from the web server, a redirect plugin, an SEO plugin, WordPress itself, or the CDN. Trace the public URL, then find the rule responsible for each hop.

    Export redirect rules through the plugin's supported interface. Table names, stored fields, and matching rules differ between plugins, so a generic SQL query is not a reliable redirect audit.

    Replace each confirmed chain with a direct rule to its intended destination. Check which other features depend on a plugin before removing or disabling it.

    Check CDN redirects separately

    When your origin returns a redirect, the CDN can add its own redirect on top. Cloudflare, Fastly, and Akamai all support edge redirect rules. If your origin returns a 301 to /new-path and your CDN has a Page Rule that also redirects /new-path to /final-path, you create a two-hop chain at the edge level. Audit CDN redirect rules separately from origin redirects and ensure they send traffic to the final destination in a single step.

    Keep Next.js redirects direct

    Next.js uses next.config.js for redirects. Each entry in the redirects() function should point directly to the final destination, never through intermediate paths:

    // next.config.js
    module.exports = {
      async redirects() {
        return [
          // Correct: direct to final
          {
            source: '/old-product',
            destination: '/products/new-name',
            permanent: true,
          },
          // The intermediate URL also points directly to the final page.
          {
            source: '/products/old-product',
            destination: '/products/new-name',
            permanent: true,
          },
        ];
      },
    };
    

    Prevent recurrence

    Keep redirect changes in one reviewable map or service. Validate destinations before release and test every changed source. Also replace internal links with the final URL so the site does not rely on its own redirects.

    Before deployment, run the literal map through the IndexLane redirect map auditor. It catches duplicate sources, conflicting destinations, self-redirects, chains, loops, and malformed entries locally in the browser. Then make live GET requests and record the status and Location header. A clean CSV cannot reveal conflicting server, application, or CDN rules.

    Keep two separate outputs:

    CheckKeepWhat it tells you
    Map analysisVersioned CSV plus structural findingsThe intended literal rules do not contradict each other
    Live verificationSource, status, Location, final URL, and hop countThe live redirect reaches the intended page

    Retest important legacy URLs after later migrations. A redirect that was direct at launch can become a chain when its destination moves again.

    Related notes

    How to spot a crawl drop in server logs

    Compare verified crawler requests with your usual traffic pattern to catch access failures, rising errors, and unexpected URL changes.

    Read article →

    Keep Googlebot access rules current when IP ranges change

    Verify crawler requests, update the correct Google IP range list, and check that your CDN or firewall actually applied the change.

    Read article →