Back to insights
Web Development

WordPress to Payload CMS: The Complete Technical Migration Guide

Techseria
TechseriaTeam

WordPress to Payload CMS: The Complete Technical Migration Guide

This is not a "why you should migrate" article. You have already decided. What you need now is the technical blueprint — the exact steps, the specific mappings, the real cost ranges, and the checklist that prevents post-launch disasters.

WordPress to Payload CMS is a genuine architectural shift. You are moving from a monolithic PHP application backed by a relational MySQL schema to a TypeScript-native, headless CMS with a flexible document-oriented or relational backend (PostgreSQL or MongoDB), a REST and GraphQL API by default, and a custom admin UI generated from code. The migration touches every layer of your stack.

This guide is structured for the engineers doing the work and the technical decision-makers approving it. Estimated reading time: 22 minutes. Estimated migration time: 4–20 weeks depending on complexity.

Understanding What You Are Actually Migrating

Before touching a single database record, map what you have. WordPress installations fall into four complexity tiers:

Tier 1 — Brochure site (£6k–£12k migration cost):

  • Under 500 pages
  • 2–4 custom post types
  • Minimal ACF fields (under 20 field groups)
  • Fewer than 5 active plugins providing functionality (not counting SEO/caching/security tools)
  • Media library under 2GB

Tier 2 — Content-rich site (£12k–£20k migration cost):

  • 500–5,000 pages
  • 5–12 custom post types
  • Complex ACF field groups including repeaters and flexible content layouts
  • 5–15 functional plugins
  • Media library 2–20GB
  • Custom taxonomies with complex relationships

Tier 3 — Application-level (£20k–£35k migration cost):

  • 5,000+ posts/pages or complex relational data
  • Multi-site WordPress installation
  • WooCommerce integration
  • Custom REST API endpoints
  • Complex user role structures
  • Media library 20GB+
  • Multiple language versions (WPML/Polylang)

Correctly identifying your tier before quoting is critical. Most migration projects that overrun budget do so because Tier 2 complexity was scoped as Tier 1.

Phase 1: The Plugin Dependency Audit

The most common migration failure point is undiscovered functional dependencies on WordPress plugins. Before writing a single line of Payload code, you must audit every active plugin and classify it into one of four categories:

Category A — Functionality to rebuild in Payload: Core business logic that your site depends on. Examples: WooCommerce (rebuild as Payload collections + custom endpoints), Events Calendar (rebuild as Events collection), Membership plugins (rebuild as Payload access control). These represent the bulk of your development work.

Category B — Functionality native to Payload: Things WordPress needed a plugin for that Payload handles natively. User authentication and roles, API access, draft/publish workflow, media uploads. These are zero-effort wins.

Category C — Functionality to handle at the infrastructure layer: Caching (now handled by your Next.js/Nuxt layer or CDN), security scanning (now handled at server/WAF level), sitemap generation (now a static generation step), redirects (now handled by your web server config or Next.js middleware).

Category D — Functionality to eliminate: Plugins you are paying for but no longer need. Page builders (Elementor, Divi, WPBakery) — Payload does not use page builders. You are replacing them with structured content and a properly built frontend. Most sites have 3–8 plugins in this category.

Audit output: For each Category A plugin, estimate rebuild complexity in developer days. This is your primary migration cost driver. A WooCommerce-equivalent in Payload for a simple product catalogue is 8–15 developer days. A complex multi-vendor WooCommerce setup with custom shipping logic is 30–60 developer days.

Phase 2: Database Schema Mapping

WordPress uses a specific MySQL schema that you must fully understand before extracting data. Here are the critical tables and their Payload equivalents:

Core WordPress Tables → Payload Collections

`wp_posts` → Multiple Payload Collections

WordPress uses `wp_posts` for everything: posts, pages, custom post types, revisions, attachments, and navigation menus — all in a single table, differentiated by `post_type`. The `post_status` column handles draft/published/trashed state.

In Payload, each post type becomes its own collection with its own schema. Your mapping:

wp_posts WHERE post_type = 'post' → payload collection: 'posts' wp_posts WHERE post_type = 'page' → payload collection: 'pages' wp_posts WHERE post_type = 'product' → payload collection: 'products'

Key columns to map:

WordPress Column Payload Field Notes

`post_title` `title` (text) Direct mapping

`post_content` `content` (richText) Requires HTML-to-Lexical conversion

`post_excerpt` `excerpt` (textarea) Direct mapping

`post_status` `_status` Payload uses `draft`/`published`

`post_date` `createdAt` Payload handles automatically

`post_modified` `updatedAt` Payload handles automatically

`post_name` (slug) `slug` (text) Direct mapping, critical for URL preservation

`post_author` (user ID) `author` (relationship to users) Requires user migration first

`wp_postmeta` → Payload Collection Fields

WordPress stores all custom field values in `wp_postmeta` as key-value pairs — an enormously flexible but poorly typed system. Every ACF field, every theme option, every plugin setting lives here as a `meta_key` / `meta_value` pair.

Your task: query `wp_postmeta` for all distinct `meta_key` values associated with each post type, then map each key to a typed Payload field. This is the most labour-intensive part of schema mapping for ACF-heavy sites.

-- Discover all meta keys for a post type SELECT DISTINCT pm.meta_key, COUNT(*) as usage_count FROM wp_postmeta pm

`wp_terms`, `wp_term_taxonomy`, `wp_term_relationships` → Payload Collections or Select Fields

WordPress taxonomies (categories, tags, and custom taxonomies) are stored across three tables. In Payload, simple taxonomies become `select` or `radio` fields. Complex hierarchical taxonomies (like product categories with multiple levels) become their own collections with `relationship` fields connecting them.

`wp_users`, `wp_usermeta` → Payload Users Collection

Payload has a built-in users collection. Map `wp_users` columns to Payload user fields. Passwords cannot be migrated (WordPress uses phpass hashing, Payload uses bcrypt) — you must trigger a password reset for all users post-migration.

Phase 3: ACF Fields → Payload Fields

Advanced Custom Fields is the primary complexity multiplier in WordPress migrations. Here is the complete mapping:

Simple Fields (Direct Mapping)

ACF Field Type Payload Field Type Notes

Text text Direct

Textarea textarea Direct

Number number Direct

Email email Direct

URL text (with validation) Add URL validation in Payload

Password text Store as text; hash on first use

Checkbox checkbox Direct

True/False checkbox Direct

Select select Map options array

Radio radio Map options array

Date Picker date Convert to ISO 8601

Color Picker text Store hex value

Relationship Fields (Require Collection Setup First)

ACF Field Type Payload Field Type Notes

Post Object relationship Must specify relatedCollection(s)

Page Link relationship Same as Post Object

Relationship relationship (hasMany) Multiple allowed

User relationship (to users) Payload users collection

Taxonomy relationship or select Depends on whether taxonomy becomes a collection

Complex Fields (Significant Rebuild Required)

ACF Repeater → Payload Array Field

ACF Repeater fields store rows in `wp_postmeta` using a specific naming convention: `field_name_0_subfield`, `field_name_1_subfield`, etc., with a `field_name` key storing the row count.

Payload's equivalent is the `array` field type with sub-fields. The migration script must parse the numbered key pattern and reconstruct arrays.

// Payload array field equivalent to ACF Repeater { name: 'teamMembers',

ACF Flexible Content → Payload Blocks Field

This is the most complex migration scenario. ACF Flexible Content allows editors to compose pages from multiple layout types — a hero block, then a two-column section, then a testimonial grid, etc. The data is stored similarly to Repeater fields but with an additional `acf_fc_layout` key identifying the layout type.

Payload's `blocks` field is the direct equivalent. Each ACF layout becomes a Payload block definition. The migration script maps `acf_fc_layout` values to Payload block slugs.

ACF Gallery → Payload Array with Upload Fields

Gallery fields store an array of attachment IDs. In Payload, this becomes an `array` field where each item is an `upload` field pointing to the media collection.

Phase 4: Media Library Migration

Media files require two distinct migration steps: file migration and database record migration.

Step 1: Migrate files

WordPress media files live in `wp-content/uploads/`, organised by year and month (`2024/03/image.jpg`). Copy the entire uploads directory to your new hosting environment or object storage (Azure Blob Storage, AWS S3, Cloudflare R2).

For large media libraries (10GB+), use `rsync` with checksum verification rather than a direct copy. Verify file counts before and after.

Step 2: Migrate media records

Each WordPress attachment (`wp_posts` where `post_type = 'attachment'`) becomes a record in Payload's media collection. The `guid` column stores the original URL. Map to Payload's `filename`, `mimeType`, `filesize`, `width`, and `height` fields.

Critical: preserve the original file paths and update your web server configuration to serve old WordPress URLs from the new location. Any external sites linking to your media must not break.

Step 3: Convert content references

WordPress stores media references as full URLs embedded in `post_content`. After migration, these URLs change. You must run a search-and-replace across all migrated content to update media URLs to their new paths — or configure URL rewriting at the server level.

For WordPress content that used `[caption]` shortcodes or Gutenberg block comments, you will need a parser to convert these to Payload's rich text format before import.

Phase 5: Writing the Migration Scripts

The migration itself runs in stages. Here is the recommended execution order:

  1. Users (no dependencies)
  2. Media (no dependencies)
  3. Taxonomies/Categories (no dependencies)
  4. Parent pages (depends on users)
  5. Child pages and posts (depends on parents, users, media, taxonomies)
  6. Custom post types (depends on all above)
  7. Menus and navigation (depends on all above)

Each stage should be:

  • Idempotent (safe to run multiple times without creating duplicates)
  • Logged (every record created, skipped, or failed should be written to a log file)
  • Resumable (track migration state so you can restart from a failure point)

Use Payload's Local API for imports, not the REST API. The Local API bypasses HTTP overhead and access control, making bulk imports 10–50x faster.

// Example: bulk import posts via Payload Local API import payload from 'payload' const migratePosts = async (wordpressPosts: WPPost[]) => {

The 34-Point Go-Live Checklist

Before cutting DNS, verify every item on this list. Missing even one of these has caused post-launch incidents on real migrations.

Content integrity (10 checks):

  1. Total page count matches between WordPress export and Payload database
  2. Total post count matches
  3. All custom post type records migrated with correct count
  4. Media file count matches (files on disk vs. records in database)
  5. All relationship fields populated (spot-check 20 records per collection)
  6. Rich text content renders correctly in frontend (no raw HTML or shortcodes visible)
  7. ACF Repeater/Flexible Content data appears correctly
  8. Featured images assigned correctly (spot-check)
  9. Post dates preserved correctly
  10. Draft posts remain as drafts; published posts published

URL and redirect integrity (6 checks):

  1. All WordPress page slugs preserved in Payload
  2. Category and tag archive URLs redirected (these will change architecture)
  3. Old WordPress media URLs redirect to new media locations
  4. `/wp-admin/` returns 404 or redirect (security)
  5. `/xmlrpc.php` returns 404 (security)
  6. 301 redirect map created and imported into web server config

SEO integrity (5 checks):

  1. Meta titles migrated from Yoast/RankMath SEO fields
  2. Meta descriptions migrated
  3. OG image assignments preserved
  4. Canonical URL tags present in frontend
  5. Sitemap generating correctly and submitted to Search Console

Authentication and access control (4 checks):

  1. Admin user accounts created with correct roles
  2. Password reset emails sent to all migrated users
  3. Public-facing content accessible without authentication
  4. Protected content requires authentication

Performance (4 checks):

  1. Core Web Vitals measured (LCP, CLS, INP) — should improve over WordPress
  2. API response times under 200ms for typical queries
  3. Image optimisation functioning (WebP conversion, lazy loading)
  4. CDN configured and serving static assets

Functional (5 checks):

  1. Contact forms functional (new implementation, not WP plugin)
  2. Search functionality operational
  3. Navigation menus correct
  4. 404 page displays correctly
  5. Analytics tracking firing on all pages

Migration Cost Summary

Complexity Tier Typical Timeline Cost Range

Tier 1 — Brochure site 4–6 weeks £6,000–£12,000

Tier 2 — Content-rich 8–14 weeks £12,000–£20,000

Tier 3 — Application-level 14–20 weeks £20,000–£35,000

These ranges assume Techseria delivering the full migration including scoping, schema design, migration scripts, frontend integration (Next.js or similar), testing, and go-live support. In-house teams with strong TypeScript capability can reduce costs by 30–40% but typically extend timelines.

Ready to Scope Your Migration?

Techseria has executed WordPress to Payload CMS migrations for organisations ranging from 200-page brochure sites to complex multi-post-type platforms with 50,000+ content records. Our migrations do not overrun budgets because we start with a fixed-fee technical audit — £2,500, delivered in 7 days — that produces your complete schema mapping, plugin dependency analysis, and a fixed project quote before any code is written.

[Book a Strategy Session](https://techseria.com/contact) to discuss your WordPress setup and get an accurate scope for your migration. Or [request a fixed-fee quote](https://techseria.com/contact) if you already know what you have and what you need.

Ready to accelerate your operations?

See how custom AI solutions, ERPNext integration, and workflow automations can lower your operating costs. Book your free 30-minute Workflow Audit with a senior engineer.

Further Reading

Recent Articles

Measuring ROI on AI Agent Deployment: The Only 5 KPIs That Actually Tell You If It's Working

The 5 KPIs that tell you if your AI agent deployment is working: cycle time, error rate, FTE savings, exception escalation rate, cost-per-transaction. Frameworks for CFOs and COOs.

Techseria

Azure DevOps for Mid-Market: Is the Complexity Worth It vs GitHub Actions?

Azure DevOps or GitHub Actions for mid-market teams? Honest comparison covering pipelines, boards, repos, pricing, and the scenarios where each wins.

Techseria

Azure AI Foundry vs Custom LLM Integration: Decision Guide for Enterprise Teams

Azure AI Foundry or custom LLM integration? This decision guide covers when each approach is right, what Azure AI Foundry provides, and what you give up by going custom.

Techseria
Techseria

Engineering the enterprise of tomorrow — from strategy through operations.

UK Address

Techseria (UK) LTD 71-75 Shelton Street, Covent Garden, London, WC2H 9JQ

India Address

Techseria Private Limited G-1209, Titanium City Center, 100 Feet Shyamal Road, Satellite, Ahmedabad – 380015

© 2026 Techseria Technologies, Inc. All rights reserved.