We use cookies to improve your experience, analyze site traffic, and personalize content. You can accept all cookies or choose which categories to allow. Learn more
Redirects in Ecommerce: 301, 410, Slug History, and Avoiding Chains (2026) | Ordiko
Guide
Redirects in Ecommerce: 301, 410, Slug History, and Avoiding Chains (2026)
When to use 301 vs 410 vs other HTTP status codes for ecommerce URL changes, how to track slug history, detect redirect chains, and avoid the common pitfalls that tank SEO.
PT45M
TL;DR. Redirects in ecommerce are about preserving SEO equity through URL changes. Use 301 for permanent moves (slug fixes, rebrands). Use 410 for permanent deletions. Track slug history per entity so old URLs auto-redirect. Detect and flatten chains weekly. Render gone pages with useful content, not generic 404.
HTTP status codes for ecommerce
Code
Name
Meaning
Use case
200
OK
Page exists
Normal product/category page
301
Moved Permanently
Use the new URL forever
Slug changes, rebrands, domain migrations
302
Found
Temporary redirect
A/B tests, geo-redirects, temporary outages
307
Temporary Redirect
Same as 302 but preserves method
API redirects with POST
FAQ
What's the practical difference between 301 and 302?
301 = permanent. Passes nearly all link equity. Caches the redirect heavily. Use for slug changes, domain migrations. 302 = temporary. Passes less equity. Doesn't cache as aggressively. Use for A/B tests or temporary outages. For most ecommerce redirects, 301 is correct.
What's the difference between 404 and 410?
404 = 'not found, might come back'. Google may keep the URL in its index for a while in case it returns. 410 = 'gone, permanently removed'. Google drops the URL faster. For permanently discontinued products, 410 is better SEO hygiene.
How many redirect hops are too many?
Two hops is the practical limit. Each hop loses 5β10% link equity and adds latency. Three or more hops is a smell. Detect and flatten them automatically.
How does Ordiko handle slug history?
Every entity table has a corresponding slug history table (e.g., product_slug_history). On slug change, a new row is inserted with the old slug; a 301 redirect is automatically written to storeRedirects. Trigger.dev weekly redirect-chain-verify task HEAD-traces redirects and flags chains and broken targets.
Related reading
308
Permanent Redirect
Same as 301 but preserves method
API redirects with POST
404
Not Found
Page doesn't exist, might come back
Typos, misremembered URLs
410
Gone
Permanently removed
Discontinued products, deleted content
For ecommerce, the common pair is 301 for moves and 410 for permanent deletes.
Suggest similar products (use pgvector cosine on the gone entity's embedding).
Provide a search box.
Have a clear "this product is no longer available" message.
Slug history per entity
When a product slug changes, the old URL must redirect to the new URL. Storing this manually is fragile. Track slug history per entity:
CREATE TABLE product_slug_history (
id SERIAL PRIMARY KEY,
product_id UUID NOT NULL,
old_slug TEXT NOT NULL,
new_slug TEXT NOT NULL,
changed_at TIMESTAMPTZ DEFAULT NOW()
);
Flatten chains: rewrite the source to point directly at the final URL.
// Before: A β B β C
await db.redirects.update({ from: '/a', to: '/b' }); // existing
// After flattening:
await db.redirects.update({ from: '/a', to: '/c' }); // rewritten
Redirect loops
A β B β A is fatal. Detect at write time:
async function writeRedirect(from: string, to: string) {
const wouldLoop = await detectLoop(from, to);
if (wouldLoop) {
throw new Error(`Redirect from ${from} to ${to} creates a loop`);
}
await db.redirects.insert({ from, to, statusCode: 301 });
}
Ping IndexNow
After writing a redirect:
await enqueueIndexNow([oldUrl, newUrl]);
The engine re-fetches the old URL, sees the 301, and updates its index.
Best practices
Keep the redirect table tight. Over time, dozens of small slug edits create dozens of redirects. Periodically flatten chains.
Don't redirect entire categories to the homepage. That's a 'soft 404' to Google. Redirect to the nearest equivalent category instead.
Avoid redirecting to noindex pages. Defeats the purpose of preserving equity.
Document redirect intent. Comment column in the redirects table helps future-you understand why.
How Ordiko handles redirects
storeRedirects table with from, to, statusCode, tenant columns.
Slug history per entity: productSlugHistory, categorySlugHistory, etc.
Auto-write of 301 on slug change.
productLifecycle.archive() writes a 410 row into storeRedirects.
Gone-paths layer renders /products/[slug]/gone with similarity recommendations.
Trigger.dev weekly task redirect-chain-verify.task.ts HEAD-traces every redirect and flags chains and broken targets.
One-click "Flatten chain" rewrites A β C directly.
IndexNow pings on every redirect creation.
FAQ
What's the practical difference between 301 and 302? 301 = permanent. Passes nearly all link equity. Caches the redirect heavily. Use for slug changes, domain migrations. 302 = temporary. Passes less equity. Doesn't cache as aggressively. Use for A/B tests or temporary outages. For most ecommerce redirects, 301 is correct.
What's the difference between 404 and 410? 404 = 'not found, might come back'. Google may keep the URL in its index for a while in case it returns. 410 = 'gone, permanently removed'. Google drops the URL faster. For permanently discontinued products, 410 is better SEO hygiene.
How many redirect hops are too many? Two hops is the practical limit. Each hop loses 5β10% link equity and adds latency. Three or more hops is a smell. Detect and flatten them automatically.
How does Ordiko handle slug history? Every entity table has a corresponding slug history table (e.g., product_slug_history). On slug change, a new row is inserted with the old slug; a 301 redirect is automatically written to storeRedirects. Trigger.dev weekly redirect-chain-verify task HEAD-traces redirects and flags chains and broken targets.