obsidian/wiki/payloadcms/performance-overview.md
2026-05-15 16:15:30 +01:00

5.1 KiB

title aliases tags sources created updated
Payload CMS — Performance Optimization
payloadcms-performance
payload-performance
payloadcms
performance
optimization
nextjs
raw/performance__overview.md
2026-05-15 2026-05-15

Payload CMS — Performance Optimization

Guide to making Payload apps run as fast as possible — database, APIs, Admin Panel, and local dev.

Database

Proximity

  • Host database in the same region as the server — cross-region latency is significant

Indexes

Queries

  • Combine multiple query optimizations together: select, depth, limit, populate
  • See wiki/payloadcms/queries → Performance section for depth/select patterns

API Request Lifecycle

Payload's request lifecycle includes hooks, access control, and validations — all add overhead.

Hooks

  • Write lightweight hooks — avoid blocking operations or unnecessary DB calls
  • Offload long-running tasks to wiki/payloadcms/jobs-queue
  • Prevent memory leaks (no unclosed streams, unbounded arrays)
  • See wiki/payloadcms/hooks → Performance section

Validations

  • Async or heavy validation functions → only run when necessary
  • Gate expensive validators with early-exit conditions
  • See wiki/payloadcms/fields-overview → Validation Performance section

Custom Admin Components

Config-Level Optimizations

Block References

Reuse a block definition across multiple collections without duplicating config:

const config = buildConfig({
  blocks: [
    { slug: 'TextBlock', fields: [{ name: 'text', type: 'text' }] },
  ],
  collections: [
    {
      slug: 'posts',
      fields: [{ name: 'content', type: 'blocks', blockReferences: ['TextBlock'], blocks: [] }],
    },
    {
      slug: 'pages',
      fields: [{ name: 'content', type: 'blocks', blockReferences: ['TextBlock'], blocks: [] }],
    },
  ],
})

Why: fewer fields to traverse for permission processing; less data sent to Admin Panel.

Cached Payload Instance

Never instantiate Payload more than once — use getPayload:

import { getPayload } from 'payload'
import config from '@payload-config'

const payload = await getPayload({ config })

Direct Database Calls

Bypass hooks, access control, and validation for known-safe operations:

// Single DB round-trip instead of fetch→update→fetch
await payload.db.updateOne({
  collection: 'posts',
  id: post.id,
  data: { title: 'New Title' },
  returning: false,  // skip returning the updated doc — saves one DB call
})

Warning: direct calls skip hooks, validations, and do NOT start a transaction automatically. returning: false is only available on payload.db.* — not the Local API.

Frontend Bundle

Tree-shake @payloadcms/ui

Only in non-admin code (front-end imports):

// Bad — bundles entire UI library
import { Button } from '@payloadcms/ui'

// Good — tree-shaken
import { Button } from '@payloadcms/ui/elements/Button'

Admin Panel custom components can still use import { Button } from '@payloadcms/ui' safely.

Local Development Speed

Turbopack (Next.js 15)

{ "scripts": { "dev": "next dev --turbo" } }

Next.js 16+ enables Turbopack by default.

Skip Server Bundle During Dev

Avoids compiling thousands of Payload modules on each dev restart.
Enabled by default in create-payload-app ≥ v3.28.0:

// next.config.js
export default withPayload(nextConfig, { devBundleServerPackages: false })

Key Takeaways

  • Same-region DB is the single biggest latency win — do this first
  • Index frequently queried fieldsindex: true is cheap to add, big query speedup
  • Use payload.db.updateOne with returning: false when you don't need the result back
  • Block references reduce config size and Admin Panel data transfer
  • getPayload — never call getPayload({ config }) multiple times; it returns a cached instance
  • Hooks are the main lifecycle cost — keep them synchronous where possible, offload heavy work to jobs
  • Dev performance: --turbo + devBundleServerPackages: false dramatically reduces cold start time
  • Frontend bundle: always use full import paths for @payloadcms/ui outside the Admin Panel