Storyblok to Payload Automated Migration Case Study: 16,500 Pages, Verified Page by Page

verified October 2026
Aliaksei Loi Senior Software Engineer
13 min

A migration case study from a large consumer site: what the client asked for, what we checked at every step, and what they own now.

TL;DR

  • A client we’ve worked with for years moved from Storyblok to Payload. Two reasons: Storyblok became expensive at this scale, and the client wanted to own the entire stack, from hosting to code. The move takes the platform subscription off the bill entirely.
  • 16,500 location pages and 439 editorial documents moved over, and not one address changed. We checked every page against the live site, including title, meta tags, canonical address, structured data, and sitemap entry.
  • Our in-house AI harness, a set of automated checks around the AI, ran the automated migration with an engineer approving every change.

The AI wrote almost all of the transfer code. It did not decide what “done” meant, and it did not accept its own work. Each of the 52 tasks closed only when a command proved it against the live site.

Why migrate from Storyblok to Payload?

The site belongs to a US-based parking service. Drivers use it to find, reserve, and pay for parking across the country. It’s a large consumer site: all legacy content describe parking in specific cities and neighborhoods, generated from a handful of templates, plus about five hundred editorial pages and articles. We know this site from the inside. A few years ago, we moved it onto Storyblok and built the entire platform on top of it, including the schema patterns that kept later changes cheap.

Having built the Storyblok version ourselves was the biggest advantage at the start. We already understood where the content oddities lay: which fields editors applied for unintended purposes, which of the 101 page building blocks truly reduced to around thirty, and which rendering rules originated as temporary fixes but are now accepted as “the way it has always been.” If another team had taken on this Storyblok to Payload migration, they would have spent the first weeks finding all of this. We started with the list already written.

At the planning stage, we agreed with the client on two points: to reduce CMS costs and to retain all the code and data on their side. Two conditions came with them, without which the move made no sense: lose no SEO, and do not let it drag on.

Requirement one: pay less

Storyblok had served the site well, but as the platform grew, so did its costs. More editors, more traffic, and API requests triggered by page updates all added to the bill. Eventually, the pricing model became a growing cost of success.

In April 2025, Storyblok introduced new pricing plans, explaining that its existing pricing “was not fully aligned with value.” Today, the largest self-serve plan includes up to 1 TB of traffic and 4 million API requests per month. Beyond those limits, pricing is negotiated.

By 2026, the platform fees had become a cost the client no longer wanted to carry. We were asked to solve that problem first.

Moving to Payload removes the platform subscription. Payload is open source, and the client already runs several products on infrastructure it has maintained for years: AWS, databases, and a team to keep everything running. The site simply moved alongside those products.

The client continues to pay for its existing AWS infrastructure and database, plus engineering time when changes are needed. But the SaaS subscription that had grown year after year is gone. The site did not need to lose any functionality to achieve that.

Payload met this requirement: a CMS the client can host, control, and develop independently, without an ongoing platform subscription.

Requirement two: everything on the client’s side

The second requirement went hand in hand with the first. On a SaaS platform, the client paid for the subscription and depended on us to make changes to the site. They wanted a different setup, and we agree with the principle: the client should be able to take the entire stack and continue developing it without us.

After the automated migration, everything lives on the client’s side:

  • Infrastructure: in their AWS environment.
  • CMS and database: open-source Payload running on their PostgreSQL.
  • Code: both the migration scripts and the site code in their repository.
  • Project knowledge: a task board generated from task files, a decision log with more than 300 entries explaining which options were rejected and why, and a short list of rules that must not be broken, with the reasoning behind each one.

A new engineer, whether in-house or from another web agency, can open the repository and answer three questions within an hour: where are we, what comes next, and why?

No conversation with us is needed to reconstruct the project history. No separate project board is required, either.

The migration harness itself lives in that repository for the duration of the automated migration. It consists of plain files and scripts the client’s team can run without us. Once the migration is complete and the site has switched over, the harness has done its job and is no longer needed.

Condition one: Zero SEO Loss: Protecting 16,500 URLs

Every one of those pages appears somewhere in search results, and together they account for a noticeable share of organic traffic. When a site undergoes an automated migration between CMSs, page addresses change quietly. The new platform adds a segment to the path, slugs get rewritten under new rules, a redirect from the old map never makes it into the new one.

Google’s own guidance is that permanent redirects pass ranking signals, and that rankings can still fluctuate during a move. The redirect itself is not the problem. The problem is the map: one wrong address in sixteen thousand, and you find out about it when traffic drops.

So we did not build a new redirect map. A published page keeps its address. That rule is written into the migration code, and a check for it runs on every pass. We carried over the 35 redirects that existed before us as they were, and we verified all 35.

Second, we compared finished pages, not fields in a database. Readers and search crawlers receive HTML, so that is what we compared against the live site:

  • Every page that does not redirect (the 35 pre-existing redirects were checked separately): the part search engines read first, identical to the live site: title, description, canonical address, indexing rules, social preview tags, structured data.
  • Sitemap: every dated entry across the sitemap files compared against the live site, yielding zero differences.
  • Rendering: beyond the head, the full rendered page on 337 pages chosen across location types and states; all 337 matched.
  • Editorial documents: 439 out of 439, with zero lost content.

All of this is run by commands, because nobody reads sixteen thousand pages by eye, and a missing line of structured data on a hundred of them looks like nothing. Our SEO migration checklist includes the rest of what we check before any launch.

Condition two: A Predictable Timeline: Defining “Done” on Day One

In our experience, most replatforming projects go over budget, almost always because of the tail: imports run “one more time,” fixes by hand, and a last-week argument about what counts as finished. The tail appears wherever “done” was never defined at the start.

We defined it before the first line of code. The project was split into 52 tasks, worked one at a time, and every task carried a command that proves it is complete. A task without such a command could not be started. How a task goes from that command to “closed” is the subject of the next section.

The order of tasks is about deadlines too. The first tasks to complete addressed the risks that could derail the project:

  • Multi-language support built into every content type from day one, because bolting it on later is painful.
  • A database limit on field-name length that fails silently and would have truncated data without an error.
  • The converter for formatted text between the two systems, tested on real pages before anyone trusted it.

Only after that did the bulk of the work begin.

To be precise about the timeline: the first working version of the transfer was ready in a day. Everything after that was proving it did not lose content. The result: 8 weeks of active work, one engineer (the author) and the AI harness, 52 tasks closed, none reopened. Eight weeks is not fast, but it was predictable from the second week, and for a deadline that matters more.

For what an automated migration like this usually costs, see our enterprise CMS migration cost breakdown.

What is an AI harness, and how did it run the automated migration?

An AI harness is simply the architecture of files and checks that dictates what an AI is allowed to do during an automated migration. The split of labor was absolute from day one: our engineers decided what had to be true, the AI built it, and automated checks verified the result.

Beneath the surface, this harness isn’t a complex AI black box; it relies on standard engineering staples—plain scripts, task files, and a test runner."

All 52 tasks followed a loop that began with a conversation, never code. The AI read the task and interrogated our engineering team until we shook hands on two things: what the result looked like, and the exact command to prove it. This is how you feed an AI the context it can’t discover on its own: the fields editors abused for things they weren’t meant for, the quirks that look like bugs but are actually features, and the exact details the client will look at first.

Whatever that conversation uncovers goes back into the task file before any code is written, and every decision goes into a decision log together with the alternatives we rejected and why. By the end, that log held more than 300 entries.

Then the AI writes the code and runs the command. A failed check blocks all further work until it passes. Then we review the change: I read it line by line and look at the result it produces, and only I accept it into the project. The command’s output is attached to the task, and the task is closed based on that output, not on a description of what was done.

“Done” therefore means three things at once:

  1. The change has been read and accepted by the engineer.
  2. The command has been run and its output is attached to the task.
  3. Nothing is left half-finished in the repository.

Two parts of the setup are worth spelling out:

  • One command runs everything: the code checks, the full test suites, and the comparisons against the live site.
  • The checks test themselves. A check can break like any other code, and a broken check lets errors through while still showing green. To catch that, the same command that runs the checks first runs each of them against a prepared trap page with a known error, say a page with its title swapped. The check has to find that error. If it does not, the check itself is broken, and the run stops before anyone trusts its green result.

That loop is what the eight weeks were made of: questions, decisions, and reading changes, 52 times over. Almost none of the transfer code in those weeks was manually typed by our team. Our work was deciding what it had to do and checking whether it did.

One case where this worked in our favor: the old site had a quirk where a paragraph made entirely of bold text rendered as a heading. I treated it as legacy we could clean up and decided not to carry the rule over. That was our call. The editorial import ran clean, the pages rendered on staging, and every check we had that day was green.

However, the comparison against the live site disagreed. It came back with 423 differences across the editorial documents, and 161 of them came from that one rule.

At that scale, this was a content change nobody had asked for, so we restored the rule and logged the reversal together with the numbers that caused it. A person reviewing those 439 documents manually would not have spotted it, because each page on its own looked fine.

What does AI automate in a CMS migration?

Let’s break the process down. In an AI-automated migration, the AI writes and runs the transfer code. The engineer decides what the result must be and accepts or rejects every change. On this Storyblok to Payload migration, the work split like this:

What the AI did

  • Wrote the mappings from Storyblok’s content model to Payload collections and blocks
  • Built the converter from Storyblok rich text to Payload’s rich text format
  • Wrote the import for 16,500 location pages, 439 editorial documents, and 1,157 media files
  • Ran the comparisons against the live site and reported every difference
  • Re-ran the transfer to pick up editors’ changes in Storyblok, moving only what had changed

What the engineer did

  • Defined “done” for each of the 52 tasks, and the command that proves it
  • Gave the AI the context it couldn’t find in the code: fields editors had used for other purposes, and quirks that were actually features
  • Read every change line by line before it reached the main branch
  • Made the judgment calls when a check and the plan disagreed

What you get from a migration run on a harness

This level of systematic verification is the new standard for quality check migrations. It leaves you with five things, all of them in the repository:

  1. A task board where every task has its own check, and the risks come first.
  2. A human review of every change before it reaches the main branch.
  3. Page addresses that did not change and cannot change unnoticed.
  4. A switch-over in which the old CMS remains available for weeks after launch, ensuring a safe transition until the client officially retires Storyblok.
  5. A repository from which a new person understands the state of the project within an hour.
Stage What we checked Result
Risks first A full round trip for one page: old CMS, transfer, new CMS, comparison of the rendered page Round trip closed before the main work began
Editorial content Every document against the live page 439 out of 439, zero lost content
Location pages Search-engine head, sitemap, redirects, rendering on a sample 16,500 moved, head identical on every non-redirecting page, sitemap with 0 differences, redirects 35 out of 35, rendering 337 out of 337
Media files Byte-for-byte comparison of every file 1,157 files moved and verified
Switch-over The site with the new source enabled against the live site Page tree identical to the live site

Four questions to ask before any CMS migration

Whoever runs your automated migration, these four questions separate a controlled project from a tail of fixes. They are the questions we answer in the first week.

  1. Which URLs will change, and who is checking every one of them? The right answer is “none”, with a check that runs on every pass.
  2. What does “done” mean for a single task, and where is the proof kept? A command and its output, attached to the task.
  3. What gets built first: the risky parts or the easy parts? Localization, data limits, and rich-text conversion first, volume later.
  4. Can we keep editing in the old CMS until the switch-over? Yes, if the import only moves what has changed.

If you are comparing vendors, our roundup of Storyblok migration companies is a fair place to start. If you are still deciding on your destination platform, we recently broke down how Payload compares to Sanity for AI-driven content, and our headless CMS migration guide covers the full process.

Where the project stands

The AI data migration is complete and proven. One step remains: the switch-over. The site already serves pages from the new CMS in the staging environment, and they match the live ones.

The date of the switch-over is the client’s call: their decision, their calendar. Until that day, the old CMS stays available, editors keep working in it, and a repeat run of the transfer picks up their edits, because it only moves what has changed. The plan for launch day follows the same discipline: the switch-over goes live, and the old CMS stays available for the weeks after.

When the switch-over happens, we will add the traffic numbers here.

Planning an AI CMS migration from Storyblok to Payload?

This is how FocusReactive approaches every headless CMS migration: with deep platform expertise, automated workflows, and strict validation checks at every stage. For a move from Storyblok to Payload, that means knowing what needs to move, verifying that it arrived completely intact, and making sure the new architecture works exactly as expected— without losing a single page of content or a fraction of search visibility.

Complete the contact form and select “Migration” as the subject. Tell us what you are moving from and where to. You get a reply within a day, a short call, and a scoped proposal in two to three days.

Storyblok to Payload migration FAQ

Yes, as long as it operates within an ai harness and cannot override its rules. Every task has an executable check, a failing check blocks new work, and a person reviews and approves every change. AI writes the code, but whether a task is considered done is determined by the check and the developer’s review.

Addresses of published pages do not change. That rule is written into the code and checked on every run. Before the switch-over, every page has to match the live one, meta tags and structured data included. The old CMS stays available until the switch-over, so going back is safe. Where a URL has to change (here none did), it gets a permanent redirect and a check that the redirect resolves, but the first choice is not to change it.

Yes. The import only moves what has changed, so a repeat run carries late edits across. Editors keep writing in the old CMS until the switch-over, and nothing they publish in that window is lost.

For a site of this size, yes. Payload is open source, so there is no platform subscription. The client pays for the infrastructure they already run, their AWS account and their database, plus engineering time when they want changes. For a small site with one or two editors, the difference is smaller. The gap opens with scale: seats, spaces, traffic, and API calls are exactly what a SaaS CMS bills for, and exactly what a large site has a lot of.

It depends on the volume and on how uniform the content is. In this case, 16,500 templated pages and 439 editorial documents took the same eight weeks I describe above: one engineer and the ai harness. The first working version of the transfer appeared in a day. The rest of the time went into proving it lost nothing. Industry averages are in ourheadless CMS migration statistics.