Skip to content
pageinspection

Redirect chains: how two hops become five, and what it costs

Nobody builds a redirect chain. Chains are what you get when two people each add one perfectly reasonable redirect, eighteen months apart, without either of them looking at what was already there. The result works, which is precisely why it survives.

The short answer

A redirect chain is two or more hops between the URL requested and the page served. Each hop costs latency for a visitor and crawl budget for a bot, and while Google follows up to ten, most other clients give up sooner. Flatten every chain by pointing the first URL directly at the final destination.

ImportantAudit check · Redirect chains

How a chain forms

A chain is a redirect whose destination is itself a redirect. Each individual rule is correct and the sequence is nobody's decision. The classic version takes two migrations: a path restructure, then a trailing-slash convention change layered on top of it, each rule written against the state of the site at the time.

A link to /old-page redirects to /blog/old-page, which redirects to /blog/new-page, which redirects again to /blog/new-page/ before returning 200. Three hops to reach one page. After flattening, the same link reaches /blog/new-page/ in a single 301.One link, three hops1/old-page3012/blog/old-page3013/blog/new-page301/blog/new-page/200After flattening: one hop/old-page301/blog/new-page/200
Every hop is a correct rule. The chain is an emergent property of the set, which is why no single rule looks wrong when you review it.

Note that a visitor never notices. The browser follows all three hops in a few hundred milliseconds and lands on the right page, so there is no bug report, no support ticket, and nothing in your analytics that looks unusual.

What each hop actually costs

Three separate costs, and they are worth separating because they have different sizes.

Latency, paid by every visitor. Each hop is a full round trip: DNS may be cached but the request, the response and the reconnection are not free. On a mobile connection three hops before the first byte of HTML is a real delay, and it is paid on every visit through that link, forever.

Crawl budget, paid by your site. Google follows a limited number of hops before giving up, and each one consumes a fetch that could have been a real page. On a large site with thousands of chained internal links, that adds up to a meaningful share of what the crawler was willing to do for you.

Signal, paid once and permanently. This is the one people overstate in both directions. Google has said it consolidates signals through redirects and that chains up to a handful of hops are followed. What is definitely true: a chain that exceeds the hop limit is not followed at all, and the destination is simply not reached. That is not a discount, it is a zero.

The reliable argument for flattening is latency and crawl budget. Anyone quoting you a precise percentage of authority lost per hop is making it up.

Check how one URL resolves

Paste a URL. This reports the status it finally returned, which tells you whether it lands on a real page. Hop counting is a link-graph property, so the widget names that limit rather than pretending to measure depth.

Check how one URL resolves

No signup required. Each free search audits one page, paste any URL to see it in action.

Flattening them

The rule is simple to state and easy to get wrong: every redirect points at the final destination, never at another redirect. Which means when you add a new rule, you also have to update the existing rules that pointed at its source.

next.config.mjs
export default {
  async redirects() {
    return [
      // Chained: the first rule sends traffic to a path
      // that the second rule then moves again.
      // { source: '/old-page', destination: '/blog/old-page', permanent: true },
      // { source: '/blog/old-page', destination: '/blog/new-page/', permanent: true },

      // Flattened: both legacy paths point at the final
      // URL, so either entry point is one hop.
      { source: '/old-page', destination: '/blog/new-page/', permanent: true },
      { source: '/blog/old-page', destination: '/blog/new-page/', permanent: true },
    ]
  },
}

On a server you are editing rules rather than a config array, and the ordering trap below applies. The equivalent in nginx:

nginx.conf
# Both old paths go straight to the final URL.
# 301 because these moves are permanent; use 302 only
# when you genuinely intend to move it back.
location = /old-page      { return 301 /blog/new-page/; }
location = /blog/old-page { return 301 /blog/new-page/; }

The mistake that recreates the chain you just removed

Redirect rules are evaluated in order, and a broad pattern rule placed above a specific one will swallow it. This is how a flattening exercise silently undoes itself: someone adds a catch-all near the top of the file, and every specific rule below it becomes the second hop of a new chain.

ordering.conf
# WRONG: the prefix rule matches first, so the specific
# rule below is unreachable and every /blog/* URL takes
# an extra hop through /articles/.
rewrite ^/blog/(.*)$ /articles/$1 permanent;
location = /blog/old-page { return 301 /blog/new-page/; }

# RIGHT: exact matches first, patterns last.
location = /blog/old-page { return 301 /blog/new-page/; }
rewrite ^/blog/(.*)$ /articles/$1 permanent;

The same hazard exists in a _redirects file, in .htaccess, and in any middleware that runs a list of matchers. Specific before general, always, and a comment above the general rule saying why it is last.

When a chain is acceptable

There are cases where one extra hop is the correct engineering answer, and a check firing on them is not telling you to change anything.

  • Protocol and host normalisation. http://example.com to https://example.com to https://www.example.com is two hops and is often unavoidable, since the HSTS upgrade and the canonical-host rule are enforced at different layers. Collapsing it means enumerating every combination in one rule set, which is usually worse to maintain.
  • Locale detection. A request to / that resolves to /en-gb/ based on the visitor is a hop by design. What matters is that the localised URLs themselves are stable and directly linkable.
  • Third-party link shorteners. Outside your control. Worth knowing about when the chain starts in a campaign URL rather than on your site.

Fix the internal links before you fix the redirects.

A redirect exists to serve inbound links you do not control. Your own pages should link straight to the final URL, so an internal link that relies on a redirect is a link that wants editing, not a rule that wants adding. This is the step people skip, and it is the one that stops chains regrowing.

Why a hop tax is not Critical

Because the destination is still reached. Traffic arrives, the page ranks, and the signal largely consolidates. What you are paying is a tax, on every visit and on your crawl budget, rather than losing the page.

It escalates in one case: when a chain ends in a 404, or exceeds the hop limit, the cost stops being a tax and becomes a loss. That situation is caught by the status-code check rather than this one, which is why the two are separated on the severity scale.

Confirming a chain is gone

Follow the URL and count the hops yourself. curl -sIL prints every response in the sequence, so the number of HTTP/ lines is the number of hops, and one 301 followed by one 200 is the target state. Browser developer tools show the same thing in the network panel.

Then re-crawl, because the internal-links half of the fix is the half you cannot verify by testing a URL. What you want to see is the count of internal links pointing at redirecting targets falling to zero. That number staying high after the rules are flattened means the chains will be back.

Questions this check raises

How many redirects in a row is too many?
Google follows up to ten hops in one crawl attempt, but that is a ceiling rather than a target. Two hops is where the cost becomes measurable for visitors on a slow connection, and other clients including some social scrapers stop at one. Treat anything past a single hop as work to be done.
Why does the chain come back after I flatten it?
Usually because the rules were flattened without changing the internal links that pointed at the old URLs. The next deploy adds a new rule in front of the existing ones, and the chain re-forms one hop longer. Update the links in the site itself, then keep the redirects as a fallback for external traffic.
Is a redirect chain ever acceptable?
One extra hop is acceptable when it is enforcing something global, such as HTTP to HTTPS and then non-www to www, and consolidating the two rules would mean maintaining a combined rule per URL. Beyond that, a chain is almost always an artefact of history rather than a decision.