50,000 nodes, 200,000 taxonomy terms, 14 content types, and 11 years of URL history to preserve. Here is what the project taught us.
Planning phase
We spent 6 weeks in discovery before writing a line of code. The most valuable output was a content inventory — a complete audit of every content type, its fields, its usage, and its editorial workflow. Without this, migration scripts become guesswork.
The migration itself
We used Drupal's Migrate API with custom source plugins to handle the more complex data transformations. The standard D7-to-D11 migration path handles basic content, but media files, pathauto patterns, and revision history all required custom handling.
URL preservation
301 redirects are not enough. We captured every URL in the D7 site (from access logs, not just the database) and implemented redirects at the Nginx level for high-traffic URLs and via Drupal's Redirect module for the long tail. Organic traffic was maintained within 5% throughout the migration.