payloadcms / payloadcms/payload

Migration JSON schema files cause Vercel serverless function size limit failures

Open
#15,501 4 comments 0 reactions 1 assignee View on GitHub

@AlessioGr is already working on this.

Since Feb 3, 2026.

Dominant language
TypeScript
Stars
44.8k
Forks
4.2k
Avg merge
2d 21h
Merged PRs (30d)
53

Description

Summary

Migration JSON schema snapshot files can cause Vercel serverless functions to exceed the 250MB unzipped size limit. These files are only needed when generating new migrations, not at runtime, but they get bundled into every serverless function.

Environment

  • Payload CMS: 3.69.0
  • Next.js: 16.0.10
  • Deployment: Vercel
  • Database: PostgreSQL (Neon) via @payloadcms/db-vercel-postgres

The Problem

Each migration creates a .json schema snapshot file alongside the .ts migration file. Over time, these accumulate:

src/migrations/
├── 20250123_181643_first_migration.json  (147KB)
├── 20250123_181643_first_migration.ts    (47KB)
├── 20250124_180431.json                  (149KB)
├── 20250124_180431.ts                    (2KB)
... (80+ migrations)

Total sizes in our project:

  • JSON schema files: 60MB
  • TS migration files: 1.2MB

The JSON files get traced by Next.js's @vercel/nft (node-file-trace) and bundled into every serverless function, pushing them over Vercel's 250MB limit.

Why outputFileTracingExcludes Doesn't Work

We tried various path formats in next.config.ts:

outputFileTracingExcludes: {
  "/*": ["./src/migrations/**"],
  // Also tried: "src/migrations/**", "**/migrations/**", etc.
}

None worked because the files are traced via file system reads during the Payload initialization, not just static imports. outputFileTracingExcludes only works for files that are traced but not actively read.

The Workaround

Delete the JSON files after migrations run but before the Next.js build (only on Vercel):

{
  "scripts": {
    "prebuild": "... && ([ -n \"$VERCEL\" ] && rm -f src/migrations/*.json || true)"
  }
}

Results:

  • Serverless function size: 248MB → 67MB (-73%)
  • Build time: 25-40 min (failing) → 6 min (passing)

Suggestions

  1. Documentation: Add a note about this in the migrations docs for Vercel users

  2. Feature: Consider a config option like excludeMigrationSnapshotsFromBundle: true that would:

    • Move JSON snapshots to a separate directory not traced by NFT
    • Or dynamically load them only when running payload migrate:create
  3. Default behavior: Consider not including JSON snapshots in the traced output since they're only needed for migration generation, not runtime

Related

Happy to provide more details or help with a PR if there's interest in a built-in solution!

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.