Skip to content
ExponaBLOG
TECHNICAL SEO FOR DEVELOPERS · DAY 018 / 100

Site migrations without losing traffic, explained simply

The playbook I use for domain and platform moves.

Expona Admin7 min read

Site migrations without losing traffic

I've done this five times now—moved platforms, changed domains, rebuilt entire URL structures—and every time I watch traffic tank right before launch, I panic. Then the redirects kick in, monitoring shows green, and rankings stabilize again. The difference between a migration that costs you 40% of traffic for months and one that barely dips comes down to a checklist most developers never see. This is the playbook I use for domain and platform moves.

The core migration steps

A successful site migration follows a sequence. Miss a step and you'll spend weeks debugging why Google forgot half your pages.

  1. Crawl and benchmark the old site — Before touching anything, you need a baseline.
  2. Build and test the redirect map — Every old URL must know where it goes.
  3. Launch with redirects live — The moment of truth.
  4. Update sitemaps and Search Console — Tell Google explicitly what changed.
  5. Monitor errors and rankings daily — The first 30 days are critical.

Let me walk through each one.

Step 1: Crawl and benchmark the old site

Run Screaming Frog or similar crawler on your current domain. You need:

  • Total page count
  • All HTTP status codes (especially soft 404s hiding as 200s)
  • Internal link structure
  • Redirect chains already in place
  • Canonical tags pointing elsewhere

Export this to a spreadsheet. I usually get the full URL list, status code, and title. This becomes your source of truth. Pull organic traffic data from Google Analytics for the last 90 days broken down by URL. You'll compare this against post-migration performance.

On my last migration—moving a ride-hailing platform from a legacy .NET monolith to microservices on NestJS—we found 340 pages we didn't even know existed. They were crawlable, had backlinks, and were driving maybe 2% of traffic. But losing them unannounced would have triggered spam alerts.

Step 2: Build and test the redirect map

This is where most migrations fail. You need a mapping file that handles three scenarios:

  • One-to-one redirects: /old-product-page → /new-product-page
  • Many-to-one redirects: Multiple old category pages → one new category
  • Orphaned pages: Pages with no equivalent on the new site

Create this map in a structured format—CSV or JSON—before you launch anything. For one-to-one moves, automation works. For many-to-one and orphans, you need human judgment.

Here's a sample redirect map structure:

html
{
  "redirects": [
    {
      "old_url": "/blog/old-seo-guide",
      "new_url": "/guides/seo-handbook",
      "type": "301",
      "notes": "Content merged and updated"
    },
    {
      "old_url": "/pricing-2023",
      "new_url": "/pricing",
      "type": "301",
      "notes": "Outdated page, consolidated"
    },
    {
      "old_url": "/legacy-api-docs",
      "new_url": "/developers",
      "type": "301",
      "notes": "Many-to-one, old API deprecated"
    }
  ]
}

Test this locally first. Write a script that validates every redirect:

html
// Node.js validation example
const redirectMap = require('./redirects.json');
const checkRedirect = async (oldUrl, newUrl) => {
  try {
    const response = await fetch(`http://localhost:3000${oldUrl}`, {
      redirect: 'manual'
    });
    if (response.status === 301 || response.status === 302) {
      console.log(`✓ ${oldUrl} → ${newUrl}`);
      return true;
    }
  } catch (e) {
    console.error(`✗ ${oldUrl} failed:`, e.message);
    return false;
  }
};

redirectMap.redirects.forEach(r => 
  checkRedirect(r.old_url, r.new_url)
);

Run this against your staging environment. Fix broken redirects before going live.

Step 3: Launch with redirects live

Pick a quiet day—mid-week, not Friday before a holiday. Your redirects should be 301s (permanent), not 302s. 301s tell search engines this is permanent and pass ranking power forward. 302s signal "temporary" and Google crawls them again later, creating duplicate content nightmares.

Check your server configuration. In Nginx:

html
server {
  listen 80;
  server_name old-domain.com;
  
  location /blog/old-post {
    return 301 https://new-domain.com/blog/new-post;
  }
  
  location / {
    return 301 https://new-domain.com$request_uri;
  }
}

For a platform change without a domain swap, implement redirects at the application level. In NestJS, I use middleware:

html
@Injectable()
export class RedirectMiddleware implements NestMiddleware {
  constructor(private redirectService: RedirectService) {}
  
  use(req: Request, res: Response, next: NextFunction) {
    const newPath = this.redirectService.getNewPath(req.path);
    if (newPath) {
      return res.redirect(301, newPath);
    }
    next();
  }
}

Have your team standing by. Monitor server logs for redirect loops or 404s on redirected URLs. If you find a broken redirect, fix it immediately—don't wait for a deploy window.

Step 4: Update sitemaps and Search Console

Create a fresh XML sitemap for the new site with only pages you want indexed. Submit it to Google Search Console immediately.

If you've migrated domains, add the new property to Search Console and mark the old one with a change of address (if available). Upload your redirect map there too if the interface supports it.

For the old domain, continue serving a sitemap with your migration landing page only. This keeps you from sending crawlers into dead ends.

Step 5: Monitor errors and rankings daily

Set up alerts in Google Search Console for:

  • Crawl errors increasing (404s, timeouts, access denied)
  • Mobile usability issues spiking
  • Coverage drops (pages no longer indexed)

Check Search Console every morning for 30 days. Look at Pages section to confirm old URLs are consolidating into new ones. A healthy migration shows the old URLs marked "Crawled - currently not indexed" with the new URL in the same cluster.

Set up a Google Data Studio dashboard pulling organic traffic, impressions, and rankings for your top 100 pages. Compare week-over-week post-migration.

Change one thing at a time

I see developers attempt domain migration, platform rebuild, and URL restructure simultaneously. When traffic drops 60%, you have no idea which change caused it.

Run these as separate migrations if possible:

  • Phase 1: New platform, same domain and URLs → Live with redirects for old code paths only
  • Phase 2 (after stabilization): New domain, same URLs → Redirects from old domain to new domain
  • Phase 3 (after Phase 2 stabilizes): New URL structure if needed → Redirects from old URLs to new URLs

If you move everything at once, you can't isolate the problem. Is the new platform slower? Did the URL rewrite break internal linking? Did you miss pages in the redirect map? You won't know.

On that ride-hailing migration, we kept the domain and URLs unchanged for two months after launching the new backend. Let the platform stabilize, let Google recrawl, let us confirm indexing was healthy. Only then did we introduce a new URL structure, which was a straightforward redirect exercise by that point.

Keep redirects for years

Your redirects aren't temporary. They're permanent infrastructure.

Old URLs live in:

  • Email archives (customers forwarding your pages to others)
  • Bookmarks (users who save links)
  • Backlinks (external sites pointing to you)
  • PDF documents distributed years ago
  • Marketing materials and print ads
  • Archived versions on the Wayback Machine

Plan to keep redirects active for a minimum of two years, preferably indefinitely. The cost is negligible. The upside is that every old link still works, users don't hit 404s, and your SEO equity stays intact.

I've seen companies disable redirects after six months and watch organic traffic crater when old backlinks get crawled again and hit 404s. Google penalizes that.

Expect a dip

Your traffic will drop. Probably 10–20% immediately after launch. This is normal.

Search engines need time to recrawl, reprocess, and re-rank the new site. Google's index updates happen in waves, not instantly. Bing is slower. By day 7, you should see recovery. By day 30, you should be back to baseline or higher.

If traffic stays low after 30 days, something is broken:

  • Broken redirects (check Search Console crawl errors)
  • Robots.txt blocking crawlers on new site
  • Noindex tags on new site (I've seen this)
  • Redirect chains (old URL → intermediate URL → final URL instead of direct)
  • Slow page load times on new platform scaring off both users and crawlers
  • Canonical tags pointing to the wrong domain

Check each one. Fix them methodically.

Common mistakes

  • Using 302 redirects instead of 301s: Search engines treat these as temporary and don't pass ranking power forward. Use 301 for permanent moves.
  • Breaking internal links: Audit every internal link on the new site. They should point to new URLs, not old ones. Don't make the browser do extra hops.
  • Forgetting about subdomains and parameters: Migrations often miss query parameters (?utm_source=...) and subdomains (blog.old-domain.com). Crawl these too.
  • Removing old site too early: Keep the old site online and serving redirects for months, not weeks.
  • Not testing redirects in production: Test locally, then test on staging against the real production database. Then go live with monitoring ready.
  • Ignoring redirect chains: If /a redirects to /b and /b redirects to /c, Google has to make three requests for one page. Flatten the chain: /a and /b both redirect directly to /c.

Key takeaways

  • Crawl and benchmark your current site before migration—you need a baseline and a complete URL inventory.
  • Build a structured redirect map, test it thoroughly, and use 301 redirects for permanent moves.
  • Launch on a quiet day with your team standing by to catch broken redirects immediately.
  • Submit new sitemaps to Google Search Console and monitor crawl errors daily for 30 days.
  • Migrate one thing at a time (platform, then domain, then URLs) so you can isolate problems.
  • Keep redirects live for years—the cost is negligible and the upside protects your SEO.
  • A 10–20% traffic dip immediately after launch is normal; a persistent drop after 30 days signals a real problem.
  • Check for broken redirects, robots.txt blocks, noindex tags, and slow page loads if traffic doesn't recover.
ShareXLinkedInReddit

Found this useful? Support the writing.

Buy me a coffee
Written by
Expona Admin
Site administrator

Comments

Loading comments…

Leave a comment

Comments are reviewed before they appear. Be kind and stay on topic.

Related articles