BuildWithMatija
Get In Touch
Back to case studies

Technical audit case study

Payload CMS Migration Audit for a High-Volume Import Pipeline

A migration trust issue and a slow import path were traced, repaired, and documented into a safer operating model for staging and production.

Client
Anonymous, German publication media agency
Industry
CMS migration, data import, and backend operations
Engagement
Migration audit, schema repair, import optimization, and operating model documentation
Strategic outcome
The project moved from an unreliable migration baseline to a verified schema path and a clearer import strategy for future environments.

The Situation

A development team had inherited a Payload CMS project backed by PostgreSQL. The codebase looked like it was running migrations — there was a migration folder, committed files, and a migration chain in index.ts. But the project had a mixed history: it had been started in Payload's dev mode, which pushes schema changes automatically, and later switched to committed migrations without reconciling the gap.

The result was a setup nobody could fully trust. One already-applied migration was empty in the latest commit. push: false wasn't actually set in the Payload config, meaning future automatic schema push was still possible. The historical database dump didn't align with the current schema. Running the migration chain against a fresh environment could silently produce the wrong schema, or fail outright.

A second concern was the data importer. A single edition import produced hundreds of writes — media, articles, PDFs, preview images, pages, relation records — all routed through the Payload local API one record at a time. Image resizes were being triggered through the media collection during import, adding Sharp processing overhead. Under heavier loads, the runtime was returning 504s.

Promoting to staging or production was blocked. The engagement was scoped to a structured technical review of both problems, a local repair, and a written operating model for going forward.

What the Audit Found

The root cause of the migration instability was straightforward: the database had been created through Payload's automatic schema push behavior and the project later switched to committed migrations without reconciling the gap. The existing migration chain couldn't be applied cleanly because the database's actual schema reflected the older push-era state.

Specific findings:

  • push: false was missing from payload.config.ts — automatic schema push was still active
  • 20260318_124327.ts, an already-applied migration, was empty in the latest commit — a classic source of migration history instability
  • Schema drift of 20 normalized statements between the restored historical dump and the current code-expected schema, across enum naming, column names, and table structure
  • The import write path paid full Payload local API overhead — validation, hooks, access control, lifecycle processing — on every individual record, making high-volume ingestion slow by design
  • Image resize processing during import was compounding the runtime load, contributing to instability under heavier imports

The migration problem and the import problem were independent in cause but compounding in effect: a team that can't trust its schema baseline and can't run imports reliably has no safe path forward.

The Outcome

Local repair was completed and verified within 3 working days.

Migration recovery:

  • push: false enforced in payload.config.ts
  • Committed migration chain restored and validated
  • Bootstrap SQL written to align the legacy database lineage with the correct historical baseline
  • Forward delta migration written and applied — covering enum renames, column renames, and structural corrections across locales, interstitials, editions, and showcases
  • All three migrations confirmed applied in correct batch order via npx payload migrate:status
  • Application startup verified against the migrated database
  • Corrected baseline dump created as the preferred starting point for all future environments

Delivered alongside the repair: a written strategy report covering the recommended production-safe migration workflow, a two-path baseline policy for disposable and persistent environments, a deployment model that moves migrations out of application startup into an explicit CI step, and a concrete import architecture direction — replacing sequential local API writes with transactional batch writes via payload.db / Drizzle ORM, with Payload's job queue for visibility, retry behavior, and worker isolation.

The team had a working migration chain, a clean baseline artifact, and a clear operating model. The path to staging and production was no longer blocked.

Why this page exists

A case study should help a future buyer recognize the actual business problem, not just admire the final build. That is the job of this page.

Need lighter references?

Need lighter-weight build references instead?

Browse other projects

Working through something similar?

If your company knows the site is wrong but the brief still says "we need a new website," the strategy layer is probably missing.

Start a conversation
Build With Matija Logo

Build with Matija

Matija Žiberna

I turn scattered business knowledge into one usable system. End-to-end system architecture, AI integration, and development.

Quick Links

Case Studies
  • Other Projects
  • How I Work
  • Blog
  • RSS Feed
  • Services

    • B2B Website Development
    • Bespoke AI Applications
    • Advisory

    Payload

    • B2B Website Development
    • Payload CMS Developer
    • Audit
    • Migration
    • Pricing
    • Payload vs Sanity
    • Payload vs WordPress
    • Payload vs Strapi
    • Payload vs Contentful

    Industries

    • Manufacturing
    • Construction

    Get in Touch

    Have a project in mind? Let's discuss how we can help your business grow.

    Book a discovery callContact me →
    © 2026BuildWithMatija•Principal-led system architecture•All rights reserved