惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

雷峰网
雷峰网
T
The Blog of Author Tim Ferriss
WordPress大学
WordPress大学
V
V2EX
Jina AI
Jina AI
S
Schneier on Security
Cyberwarzone
Cyberwarzone
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
PCI Perspectives
PCI Perspectives
美团技术团队
小众软件
小众软件
L
LangChain Blog
N
Netflix TechBlog - Medium
大猫的无限游戏
大猫的无限游戏
T
Threatpost
T
Tor Project blog
K
Kaspersky official blog
Microsoft Security Blog
Microsoft Security Blog
Security Archives - TechRepublic
Security Archives - TechRepublic
Security Latest
Security Latest
H
Heimdal Security Blog
N
News and Events Feed by Topic
T
Threat Research - Cisco Blogs
J
Java Code Geeks
H
Hackread – Cybersecurity News, Data Breaches, AI and More
T
Tailwind CSS Blog
C
CXSECURITY Database RSS Feed - CXSecurity.com
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
M
MIT News - Artificial intelligence
Apple Machine Learning Research
Apple Machine Learning Research
N
News | PayPal Newsroom
I
Intezer
博客园 - 聂微东
U
Unit 42
Cisco Talos Blog
Cisco Talos Blog
量子位
T
The Exploit Database - CXSecurity.com
Last Week in AI
Last Week in AI
博客园_首页
月光博客
月光博客
Webroot Blog
Webroot Blog
I
InfoQ
The Cloudflare Blog
Attack and Defense Labs
Attack and Defense Labs
人人都是产品经理
人人都是产品经理
Project Zero
Project Zero
Hacker News: Ask HN
Hacker News: Ask HN
IT之家
IT之家
Google DeepMind News
Google DeepMind News
C
Cisco Blogs

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant Common SOC 2 Failures (Real World) Stop Vibe-Checking Your AI App: A Practical Guide to Evals How to Use SonarQube and SonarScanner Locally to Level Up Your Code Quality Your Next To-Do App Is Dead — I Replaced Mine with an OpenClaw AI Sign a Nostr event in 60 lines of Python using coincurve — no nostr-sdk, no nbxplorer, no rust toolchain ITGC Audit Explained Like You’re in Big 4 Patch Tuesday abril 2026: Microsoft parcha 163 vulnerabilidades y un zero-day en SharePoint Stop scraping everything: a better way to track competitor price changes Listing on MCPize + the Official MCP Registry while routing payments OUTSIDE the marketplace — how I kept 100% of my x402 revenue Building an AI-Powered Risk Intelligence System Using Serverless Architecture Why We Ripped Function Overloading Out of Our AI Toolchain Testing AI-Generated Code: How to Actually Know If It Works SaaS Churn Is Killing Your Business. Here Is What to Do About It (Without a Support Team) The Speed of AI Is No Longer Linear - And Self-Improving Models Are Why How to Implement RBAC for MCP Tools: A Practical Guide for Engineering Teams From Standard Quote to Persuasive Proposal: AI Automation for Arborists I built a CLI that scaffolds complete multi-tenant SaaS apps Axios CVE-2025–62718: The Silent SSRF Bug That Could Be Hiding in Your Node.js App Right Now The dashboard that ended our friendship Data Pipelines Explained Simply (and How to Build Them with Python) The Hidden Cost of AI Systems Nobody Talks About. undefined vs undeclared, and how typeof behaves Switching from file-based jobs to NATS/Kafka in Rust without changing code io_uring Adventures: Rust Servers That Love Syscalls Why Agentic AI is Killing the Traditional Database The POUR principles of web accessibility for developers and designers Quantum Neural Network 3D — A Deep Dive into Interactive WebGL Visualization How To Install Caveman In Codex On macOS And Windows Automation Pipeline Reliability: Why Your Workflow Breaks When Nobody Is Watching I Built an 'Open World' AI Coding Agent — It Works From ANY Folder From Freelancing to Product: A Tech Service Company's SaaS Transformation China's AI Giants: Adding Tencent Hunyuan & ByteDance Doubao to AI University (74 Providers) On the Vibe Coders and Their Lies clerk: Auto-Summarize Your Claude Code Sessions AI Weekly — 2026/04/10–04/17 | The Model Lockdown Is Here, but the Toolchain Is the Real Battleground AI 週報 — 2026/04/10–2026/04/17 模型封鎖潮來了,但工具鏈才是真戰場 Maybe this is how Open-Source apps are born... 🚀 Fine-Tune LLMs with LoRA and QLoRA: 2026 Guide tRPC v11 + Next.js App Router: End-to-End Type Safety Without the Boilerplate ShadCN UI in 2026: Why I Stopped Installing Component Libraries and Started Owning My Components SaaS Billing in React Server Components: Stripe + Supabase Without a Single `useEffect` Join our DEV Weekend Challenge — $1,000 in Prizes Across TEN winners! Submissions Due April 20 at 6:59 AM UTC. Implementing FSRS Spaced Repetition in Flutter + Supabase — Adding Memory Science to an AI Learning App "I Texted My Localhost From the Train — Claude Code Fixed the Bug Before I Got Home" I Built a Sales Prep AI and It Went Deeper Than Expected Design to Code #2: One JSON, Eleven Outputs Solving the 100M-Row Problem: A Summary Table Pattern for High-Volume Push Notification Logs Flutter Web With Wasm: What Actually Changes For Developers I Built 50 Royalty-Free Soundtracks for My Side Project in a Weekend Using AI Music Generation The Vibe Coding Security Checklist: 7 Things to Check Before You Ship Stop Letting Googlebot Guess Fix Your React App's SEO Right Desconstruindo o Streaming do LinkedIn: Como Criar um Engine de Extração de Vídeo de Alta Performance com HLS e FFmpeg (EDA Part-1) EDA (Exploratory Data Analysis) Explained With Real Life — Why Looking at Your Data Is the Most Important Step in Machine Learning Brand Relationship Management at Scale: Our 4-Touch Outreach System for 200+ Brands Why String.fromEnvironment() Might Return an Empty String in Dart JGuardrails 1.0.0 — Hardening Java LLM Apps Against Jailbreaks, Toxicity, and Prompt Injection Plan and Schedule a Full Week of Threads Content From One Claude Conversation Coding Cat Oran Ep3, Five Tables Changed Everything Updated: BFF Pattern I'm done watching freelancers get buried by 200 proposals. So I'm building the alternative. This is my first post BFS Algorithm in Java Step by Step Tutorial with Examples Tracking LLM Pricing Monthly: An Open Dataset for 22 AI Models How We Measure Content ROI on a Comparison Site: Revenue Attribution Without Perfect Data Introducing Nova AI Ops: The AI-Native Operating System for SRE Teams I built a free desktop video downloader for Windows — Grabbit How Talkie OCR Helps Vision-Impaired & Dyslexic Users Read the World Around Them VRCFaceTracking安装和iPhone面捕配置教程,有bug Even CrowdStrike Can't See Your Agents The Automation Gold Rush: What n8n Workflows and Claude Are Opening Up for Developers Right Now
The Hard Way: Lessons Learned from Real-World Data Migration Projects
Kushang Tail · 2026-04-30 · via DEV Community

The Hard Way: Lessons Learned from Real-World Data Migration Projects

How three years of ignoring data migration nearly derailed my dev career — and what I spent the next years mastering.


What Is Data Migration?

Data migration is the process of moving data from one system, format, location, or environment to another. It sounds straightforward — until it isn't.

At its core, data migration is about transfer + transformation + validation. You're not just copying files; you're ensuring that data arrives at its destination intact, usable, and consistent with the target system's structure and rules.

Types of Data Migration

1. Storage Migration
Moving data from one physical or cloud storage system to another — e.g., from on-premise servers to AWS S3 or Google Cloud Storage.

2. Database Migration
Transferring data between database engines (MySQL → PostgreSQL), versions, or schemas. This often involves restructuring tables, rewriting queries, and handling incompatible data types.

3. Application Migration
Moving data as part of migrating from one application to another — e.g., from a legacy CRM to Salesforce, or from a static HTML site to a CMS like WordPress.

4. Cloud Migration
Migrating workloads and data from on-premise infrastructure to cloud platforms, or between cloud providers.

5. Business Process Migration
Triggered by mergers, acquisitions, or system upgrades — involves consolidating or restructuring data from multiple sources into a unified system.

6. WordPress-Specific Migration (more on this shortly)
A category unto itself — involving database exports, media files, plugins, theme settings, serialized data, and URL structures.


Data Migration in WordPress

WordPress stores almost everything in a MySQL database — posts, pages, users, settings, metadata, plugin configurations — and media files separately on the server. This dual structure makes WordPress migrations uniquely nuanced.

A WordPress migration typically involves:

  • Database (wp_* tables) — posts, terms, options, users, meta
  • wp-content/uploads/ — all media files
  • wp-config.php — environment-specific configuration
  • Theme and plugin files — code that must be compatible with the target environment
  • Serialized data — PHP-serialized strings stored in the database that break if you do a naive find-and-replace on URLs

WordPress migrations are common in scenarios like:

  • Changing domains or hosting providers
  • Moving from single site to Multisite
  • Migrating to managed or enterprise-grade hosting (WP VIP, Kinsta, Pagely)
  • Rebuilding a legacy site in WordPress

The Problem: What Goes Wrong (And Why)

Data migration failures are more common than the industry likes to admit. Here's what I've seen cause the most damage:

1. Broken URLs and Serialized Data

WordPress stores serialized PHP arrays in the database. A simple SQL FIND & REPLACE on the old domain will corrupt those strings because they contain byte-length metadata. The result: broken theme options, widget configurations, and plugin settings that silently fail.

2. Missing or Orphaned Media Files

The database records can transfer perfectly while media files are left behind on the old server — broken images everywhere, no obvious error.

3. Character Encoding Issues

Moving between servers with different MySQL collations (e.g., utf8 vs utf8mb4) can corrupt special characters, emojis, and multilingual content.

4. Plugin and Theme Incompatibilities

A plugin that worked on PHP 7.4 + MySQL 5.7 may fail silently or fatally on PHP 8.1 + MySQL 8.0 on the new host.

5. Skipping the Staging Phase

Going straight to production without a staging test is the single most common and most costly mistake. There's no undo button on a live site.

6. No Pre/Post Validation Checklist

Without documented baselines — post count, user count, page structure, form behavior — you won't know what broke until a user reports it.

7. SEO and Permalink Damage

URL structure changes without proper redirects tank search rankings. .htaccess rules and WordPress permalink settings must be verified post-migration.

8. Caching and CDN Serving Stale Data

After a migration, cached content from the old server can make the new site appear broken even when it isn't.


My Story: The Career Cost of Skipping This Skill

Let me be honest with you.

I spent my first three years in web development building things — WordPress themes, custom plugins, client websites. I was comfortable with HTML, CSS, PHP, and JavaScript. I thought I knew WordPress well.

What I didn't realize was that I had never touched data migration seriously. Not once.

When projects came up that required moving a site to a new server, changing domains, or restructuring content into a Multisite setup, I either avoided them or quietly handed them off. I told myself it wasn't "real development work."

That belief cost me. I walked away from projects I should have taken. I didn't get past certain interview stages at companies where migration experience was table stakes. Good opportunities at agencies working with enterprise WordPress clients — gone, because I couldn't answer questions about wp search-replace, serialized data, or staging workflows.

It wasn't a sudden failure. It was a slow leak — projects I compromised on, roles I wasn't confident enough to pursue, skills gaps that compounded over time.

Eventually, I decided to stop avoiding it.


The Safety Steps: How to Prevent Migration Disasters

Before touching any migration, build these habits:

✅ 1. Full Backup — Verified

Back up the database AND all files. Test that the backup actually restores. A backup you haven't verified is not a backup.

✅ 2. Document the Current State

Record baseline metrics: number of posts, pages, users, media files, active plugins, PHP version, MySQL version, WordPress version. Screenshot key pages. Run a broken link audit. You need a reference point.

✅ 3. Use a Staging Environment — Always

Never migrate directly to production. Set up a staging server (or use a local environment like LocalWP) that mirrors the production setup. Test everything there first.

✅ 4. Use WP-CLI for Reliable Search-Replace

Use wp search-replace with the --precise flag rather than direct SQL queries. This handles serialized data safely.

✅ 5. Verify DNS Propagation Separately

Don't conflate "migration complete" with "DNS updated." Test via hosts file override or a staging URL before pointing the domain.

✅ 6. Test Forms, Checkout Flows, and Dynamic Features

Static content is easy to verify. Test everything interactive: contact forms, WooCommerce checkout, membership logins, API integrations.

✅ 7. Have a Rollback Plan

Know exactly how you'll revert if something goes wrong. Document the steps. Set a rollback deadline during the migration window.


The Learning Curve: How Data Migration Actually Works

After committing to learning this properly, I built a workflow I still use today. Here's the foundation:

The Staging-First Philosophy

Every migration lives and dies by the staging environment. The workflow is always:

Development / Local → Staging → Production

Enter fullscreen mode Exit fullscreen mode

Never skip staging. Never.

Before Migration: Pre-Flight Checklist

  1. Audit the source site — document all plugins, theme, PHP/MySQL versions, custom tables, cron jobs
  2. Backup everything — full database dump + all files, stored off-server
  3. Verify the target environment — PHP version, MySQL version, disk space, server software (Apache/Nginx), SSL
  4. Set up staging — mirror the production environment as closely as possible
  5. Notify stakeholders — plan the migration window, communicate downtime if needed
  6. Freeze content on the source site (put it in read-only or maintenance mode) before the final migration pass

The Migration Process (Step by Step)

Step 1 — Export the database

mysqldump -u DB_USER -p DB_NAME > backup.sql
# Or with WP-CLI:
wp db export backup.sql

Enter fullscreen mode Exit fullscreen mode

Step 2 — Transfer files

rsync -avz --progress /path/to/wp-content/ user@newserver:/path/to/wp-content/

Enter fullscreen mode Exit fullscreen mode

Step 3 — Import database on target

wp db import backup.sql

Enter fullscreen mode Exit fullscreen mode

Step 4 — Update wp-config.php with new DB credentials, table prefix, and environment constants.

Step 5 — Run search-replace for the new domain

wp search-replace 'https://oldsite.com' 'https://newsite.com' --precise --all-tables

Enter fullscreen mode Exit fullscreen mode

Step 6 — Flush rewrites and caches

wp rewrite flush
wp cache flush

Enter fullscreen mode Exit fullscreen mode

Step 7 — Validate on staging — check all pages, forms, media, admin panel, user logins.

Step 8 — Go live — point DNS, verify SSL, run final flush.

After Migration: Post-Flight Checklist

  • [ ] All pages and posts load correctly
  • [ ] Images and media files display properly
  • [ ] Forms submit and send notifications
  • [ ] User accounts and roles intact
  • [ ] Admin panel fully functional
  • [ ] Plugins activated and configured correctly
  • [ ] SSL certificate active and no mixed content warnings
  • [ ] Redirects in place for any changed URLs
  • [ ] SEO plugin settings preserved (sitemaps, meta, robots.txt)
  • [ ] Google Analytics / Tag Manager firing correctly
  • [ ] Page speed acceptable (run Lighthouse)
  • [ ] Broken link scan complete

Monitor After Migration — For Weeks

Don't close the loop after go-live. Monitor actively:

  • Week 1: Check server logs daily. Watch for 404s, PHP errors, failed cron jobs.
  • Week 2–3: Monitor Google Search Console for crawl errors or ranking drops.
  • Week 4: Review uptime reports, form submissions, and any user-reported issues.
  • Set up uptime monitoring (UptimeRobot, Better Uptime) before you go live — not after.

What I Learned: Real Migration Scenarios

1. Static HTML Site → WordPress

This is a foundational migration type. The source has no database — everything lives in HTML files.

The process:

  • Inventory all HTML pages and map them to WordPress post types (pages, posts, custom types)
  • Extract content and import using WP-CLI or a custom script / WXR importer
  • Rewrite internal links to match WordPress permalink structure
  • Migrate images to wp-content/uploads/ and update references in content
  • Set up 301 redirects from old HTML URLs (e.g., /about.html) to new WordPress URLs (/about/)
  • Validate all redirects, check for orphaned pages

Key tool: WordPress Importer plugin, WP All Import for structured data, custom PHP scripts for bulk content.


2. WordPress Single Site → WordPress Multisite (Subdirectory)

This is one of the more technically involved migrations. You're converting a standalone WordPress install into a network node.

Steps:

  • Enable Multisite in wp-config.php and wp-admin/network/setup (choose subdirectory)
  • Run the network setup, update wp-config.php and .htaccess with network rules
  • Create the subsite at the target subdirectory path
  • Export content from the original site (WXR file or direct DB migration)
  • Import into the new subsite — users, posts, media, settings
  • Reassign user roles within the network context (Network Admin vs site-level roles)
  • Verify media uploads path (/wp-content/uploads/sites/[ID]/) is correctly mapped
  • Run wp search-replace scoped to the subsite's tables

Watch out for: plugins that aren't Multisite-compatible, user role conflicts, and network-activated vs site-activated plugin behavior differences.


3. WordPress to WordPress — New Domain and Hosting (WP-CLI Workflow)

This is the most common migration scenario, and WP-CLI makes it reliable.

# On the source server — export DB
wp db export old-site-backup.sql --add-drop-table

# Transfer files
rsync -avz public_html/ user@newhost:/home/user/public_html/

# On the new server — import DB
wp db import old-site-backup.sql

# Update site URL and home
wp option update siteurl 'https://newdomain.com'
wp option update home 'https://newdomain.com'

# Search and replace all instances of old domain
wp search-replace 'https://olddomain.com' 'https://newdomain.com' \
  --precise \
  --all-tables \
  --report-changed-only

# Flush permalinks and cache
wp rewrite flush --hard
wp cache flush

# Verify user count and post count match source
wp user list --format=count
wp post list --post_status=publish --format=count

Enter fullscreen mode Exit fullscreen mode

Post-migration, set up 301 redirects on the old domain pointing to the new one. Keep the old domain active (don't let it expire) for at least 6–12 months to preserve link equity.


4. WordPress → WordPress VIP

WordPress VIP is an enterprise-grade managed platform with a strict code review process and a read-only production filesystem. Migrating to VIP is as much a code audit as it is a data migration.

Key differences on VIP:

  • No direct filesystem writes in production — uploaded files go to a distributed filesystem (VIP Files)
  • All code must pass VIP's automated and manual code review before deployment
  • No direct database access — use VIP's tooling
  • Plugin approval required — not all plugins are VIP-compatible
  • Local development uses vip dev-env (Docker-based local environment)

Migration steps:

  • Audit all custom plugins and themes against VIP coding standards
  • Replace any code that writes to the filesystem directly
  • Use VIP's media migration tools to transfer uploads
  • Import content via VIP's data migration pipeline (coordinate with VIP support)
  • Run full QA on VIP's staging environment before production launch
  • Monitor VIP's log dashboard post-launch

This migration typically requires coordination with the VIP team — it's not a solo operation.


5. Enterprise WordPress Site → WordPress Multisite (Subdomain)

This scenario often emerges from brand consolidation — multiple standalone WordPress sites being brought under a single Multisite network, each on its own subdomain (brand.example.com).

Challenges at enterprise scale:

  • High post/page volume — imports must be batched to avoid timeouts
  • Multiple user bases with different roles that need consolidation
  • Multiple third-party integrations (CRMs, DAMs, marketing automation) tied to the old site URLs
  • SEO preservation across all migrated properties
  • Editorial workflow tools (editorial calendars, approval flows) that must be reconfigured for the network

Process:

  • Set up Multisite with subdomain structure
  • Map brand.example.com subdomains using WordPress's domain mapping or a plugin like Mercator
  • Migrate each site individually and sequentially — never in parallel
  • Consolidate users carefully, reconciling duplicate accounts across sites
  • Update all third-party integrations one by one, confirming webhooks, API endpoints, and OAuth tokens
  • Perform site-by-site QA with dedicated checklists per subdomain
  • Coordinate DNS changes in batches with rollback windows per site

At this scale, automation matters — write scripts, use wp eval-file, lean on WP-CLI's --url flag to target specific subsites in the network.


Closing Thoughts

Data migration is not glamorous. It doesn't have a flashy demo. Nobody tweets about a successful database import.

But it is one of the most consequential skills a WordPress developer can have. Sites break in migration. Data gets lost. SEO disappears overnight. Businesses lose revenue.

Learning it properly — staging first, validating obsessively, monitoring after go-live — is what separates developers who can be trusted with production systems from those who can't.

I learned it the hard way. You don't have to.


If you've been through a migration disaster (or a migration victory), share it in the comments. The real lessons are always in the edge cases.