🇹🇷 Türkçe: Bu yazının Türkçesini oku →

Of all the platforms I have watched fade, Drupal is the one I find genuinely sad. It was the credible answer to a real question — the secure, enterprise-grade, open-source CMS. Universities ran it. Governments ran it. The White House ran it. When a serious client would not touch WordPress because “anyone can see the code,” Drupal was the open-source system they would trust.

Then Drupal 7 became Drupal 8, the whole architecture was rebuilt on Symfony, and the migration was brutal enough that people simply left. Small and mid-size projects went to WordPress and Webflow. Large enterprise went to headless or a DXP. Drupal got squeezed from both sides — not because the software got worse, but because the upgrade path asked people to rebuild their sites, and a lot of them decided that if they had to rebuild anyway, they would rebuild somewhere else.

That is why I take this migration personally. I will explain why in a minute. First, the plain-language version for anyone deciding whether to make the move.

Why teams leave Drupal for WordPress

The reasons are rarely about the code quality. Drupal’s code is good. The reasons are about people and time:

  • The talent pool. You can hire a WordPress developer this afternoon. Drupal developers are fewer, more expensive, and harder to replace when one leaves. For a mid-size organisation, that is an operational risk that grows every year.
  • Editorial friction. Drupal’s admin is powerful and unforgiving. Content editors who just want to publish a page often need a developer’s help to do it. WordPress with the block editor and ACF gives most of that back to the editors.
  • The upgrade wound. Teams that lived through Drupal 7 → 8 remember it, and they do not want to do it again at every major version. WordPress’s promise — that a site built years ago still runs after an update — is exactly the promise Drupal broke.
  • Cost. Fewer developers, longer builds, and heavier hosting add up. For a content site, WordPress is simply cheaper to run.

Why this one is personal

I did not learn the lesson of Drupal by reading about it. I learned it by building a CMS that made the same mistake.

Years ago, because we could not sell WordPress to enterprise clients in that era, we built our own CMS on Microsoft’s ASPX stack. We modelled it on WordPress because we had studied WordPress and knew the architecture was smart. It came out genuinely well. Dozens of agencies built on it. And then we hit a wall entirely of our own making: our CMS had no backward compatibility. Every new version forgot the past. To us that was fine — we were always on the newest build. To everyone using it, every release was a catastrophe, because their data had to be migrated by hand each time. We could not carry that weight. We gave up. A major bank still runs that abandoned system today, kept alive by hand, because we walked away and they could not follow.

That is the Drupal 7 → 8 story from the inside. When you break the past, you do not just create work — you make people ask whether they should follow you at all. WordPress survives precisely because it refuses to do this. Update it today and code from a decade ago mostly still runs. That is not a technical footnote. It is the entire difference between an asset and a liability, and it is the reason a Drupal migration so often ends at WordPress specifically.

How I plan a Drupal migration

Drupal is more structured than most people expect, which is good news for a migration — structured content maps cleanly when you respect the structure. My method, briefly:

  1. Inventory the model. Every content type, every field, every vocabulary, every paragraph type, every view, every URL alias. Draw the shape before you move it.
  2. Prune. A long-lived Drupal site is full of fields and content types created for reasons nobody remembers. Migration is your one chance to leave them behind. Take it.
  3. Map to WordPress. Content types become custom post types, fields become ACF fields, vocabularies become taxonomies, paragraphs become blocks. Flatten what does not earn its structure.
  4. Build the empty target first, and validate it with the editors who will live in it.
  5. Transform and dry-run on staging, repeatedly. Never straight to production.
  6. Redirects before cutover. Drupal’s URL aliases are a gift here — they are your redirect map, ready-made.
  7. Cut over, then keep watching until the editors publish without calling you.

The Technical Part: Where a Drupal Migration Actually Breaks

Here is where the details decide the outcome. If you are the developer doing the work, this is the section to keep.

Nodes, content types, and fields map well — paragraphs do not

Drupal nodes map naturally to WordPress posts, content types to custom post types, and Field API fields to ACF fields. That part is pleasant. The trap is Paragraphs — Drupal’s reusable, nestable content components, which many modern Drupal sites lean on heavily for page building. There is no 1:1 WordPress equivalent. You must decide, per paragraph type, whether it becomes a Gutenberg block, a block pattern, or an ACF flexible-content layout — and then handle every type by hand. Nested paragraphs (paragraphs inside paragraphs) are especially painful; flatten them deliberately rather than hoping a converter guesses right.

Text formats and the body field

Drupal stores body content as HTML filtered through a text format (Filtered HTML, Full HTML, Restricted). The stored markup depends on which format was applied, and it can contain Drupal-specific tokens, media embed tags (<drupal-media> / <drupal-entity>), and filter artifacts. Dropping this raw into a WordPress core/html block often works, but embedded media tags and inline entity references will not render. Inventory the embed patterns in your body fields and write handlers for them, or you will publish posts with broken media placeholders.

Taxonomy, and the term-reference two-pass problem

Vocabularies become WordPress taxonomies cleanly, but term references — like relationships between nodes — point at Drupal term IDs that mean nothing in WordPress. Import in two passes: first migrate every node and term and build a map of old Drupal IDs to new WordPress IDs, then rewrite every reference and term assignment using that map. Preserve the original Drupal nid/tid in post meta until the second pass finishes. Watch for term hierarchy — Drupal vocabularies can be deeply nested, and the parent relationships have to be rebuilt, not just the terms.

Password hashes do not port

Drupal and WordPress hash passwords differently, and the hashes are not interchangeable. You cannot simply copy the user table. Either force a password reset for all users at cutover (the clean option), or install a bridge that re-hashes a Drupal password on first successful login. Decide this before you promise a “seamless” account migration, because a silent broken login on day one is how you lose the client’s trust immediately. Map Drupal roles to WordPress roles by hand — the role models do not align automatically.

Views, blocks, and display logic do not migrate

This is the one that surprises project managers. A Drupal site’s Views — its listings, feeds, filtered pages — are configuration, not content. They do not export into WordPress. Every view has to be rebuilt as a WordPress query, block, or template. The same is true for Drupal’s block layouts and any custom display logic. Budget for reimplementing the site’s dynamic pages; the content moves, but the machinery that arranges it does not.

Multilingual

If the site uses Drupal’s content translation, decide the WordPress target — multisite, Polylang, or WPML — before migrating, because each models translations differently and the transform that splits Drupal’s per-language field values into your chosen structure is not trivial. I have run five-language multisites and I will repeat what I always say: multilingual is an architecture problem, not a translation problem. Decide the architecture first.

Media entities and files

Older Drupal stored files as file-field attachments; newer Drupal uses media entities with their own fields and reusability. Both need downloading and re-importing into the WordPress media library, and every reference — in body fields and in media-reference fields — has to be rewritten to the new attachment IDs and URLs. Do not forget the files referenced inside rich text; those are the ones that quietly break.

A note on tooling

Plugins like FG Drupal to WordPress exist and are a reasonable starting point for straightforward sites. But the moment you have paragraphs, custom text formats, non-trivial taxonomy hierarchies, or multilingual content, you will outgrow the plugin and need a custom transform working from a database snapshot. Snapshot the Drupal database, run your transform against the frozen copy, and repeat until the output is boring — never migrate against a moving production database.


My honest closing position

Drupal did not deserve what happened to it. It was a good system that broke faith with its users at one critical version, and a lot of them never came back. If you are one of the teams that stayed, and you are now deciding to move, WordPress is the natural destination — not because it is more powerful, but because it made the opposite bet. It chose to carry the past forward, unglamorously, for twenty years, and that choice is exactly what a migrating Drupal team is looking for.

Map the model. Prune hard. Handle paragraphs and text formats by hand. Do taxonomy in two passes. Plan for password resets. Rebuild the views. Set your redirects from the URL aliases before cutover.

Do that, and the content lands somewhere it can stay accurate and stay alive without asking anyone to rebuild it again in three years — which, after watching Drupal learn this the hard way and learning it the hard way myself, is the only outcome I actually care about.


One More Thing: But Can’t WordPress Just Do What Drupal Does?

Here is the objection I get from every serious Drupal team the moment they consider moving: WordPress can’t really do what Drupal did — the structured content, the fields, the taxonomy, the decoupled front-end. It’s just a blog. No. It isn’t, and as WP Clan we are not going to shortchange WordPress to make the migration sound easier than it is. WordPress already does everything Drupal did.

Custom post types and ACF give you Drupal’s content types and Field API. Taxonomies give you vocabularies and hierarchical terms. Multisite, Polylang and WPML cover the multilingual story. And crucially, WordPress does it on top of the one thing Drupal broke at 7 → 8: backward compatibility. You get the structure without the rebuild-every-major-version tax.

And if what you actually liked about Drupal was the decoupled, JSON:API story — the headless option — WordPress matches that too, and it is not new to it:

  • REST API in core since late 2016 — nearly a decade of production hardening, the direct analogue to Drupal’s JSON:API.
  • WPGraphQL, now Automattic-backed and heading toward canonical status, if you prefer a GraphQL layer over your content.
  • The ecosystem Drupal never had — WooCommerce for real commerce, a plugin economy you don’t rebuild from scratch, editorial power for humans, not just developers.
  • No per-seat pricing, no usage meter, and ownership — nobody can buy WordPress out from under you.

Drupal genuinely did structured content well; I said so, and I meant it. But “we want structured content and an API” is not a reason to fear leaving Drupal — WordPress does all of it, carries the past forward instead of forcing a rebuild, and hands you an ecosystem on top. You lose nothing. You gain the toolbox.

Leave a Reply

Your email address will not be published. Required fields are marked *

Close Search Window