payloadcms/payload

Payload is the open-source, fullstack Next.js framework, giving you instant backend superpowers. Get a full TypeScript backend and admin panel instantly. Use Payload as a headless CMS or for building powerful applications.

41,910 stars TypeScript 10 components

Builds TypeScript fullstack applications with instant backend APIs and admin panels using Next.js

Data flows through Payload in multiple patterns: Configuration-driven setup loads user configs and generates database schemas and API routes. Request processing parses incoming HTTP/GraphQL requests, applies access control and validation, executes database operations through adapters, runs hooks, and returns formatted responses. Content creation flows from admin UI forms through validation, hooks, storage adapters for files, and database persistence. The system maintains type safety throughout by generating TypeScript types from configurations.

Under the hood, the system uses 4 feedback loops, 4 data pools, 5 control points to manage its runtime behavior.

A 10-component fullstack. 6311 files analyzed. Data flows through 7 distinct pipeline stages.

How Data Flows Through the System

Data flows through Payload in multiple patterns: Configuration-driven setup loads user configs and generates database schemas and API routes. Request processing parses incoming HTTP/GraphQL requests, applies access control and validation, executes database operations through adapters, runs hooks, and returns formatted responses. Content creation flows from admin UI forms through validation, hooks, storage adapters for files, and database persistence. The system maintains type safety throughout by generating TypeScript types from configurations.

  1. Load Configuration — The Payload constructor reads payload.config.ts file, validates collection and global configurations, initializes plugins, and sets up the runtime configuration object that drives all subsequent operations
  2. Generate Database Schema — SchemaGenerator transforms collection field definitions into database-specific table schemas through the selected DatabaseAdapter, creating tables, indexes, and relationships based on field configurations [PayloadConfig]
  3. Process API Request — CollectionRouter receives HTTP requests, parses query parameters and request bodies, validates against collection access rules, and constructs AdapterQuery objects for database operations
  4. Execute Database Operation — DatabaseAdapter translates AdapterQuery into database-specific queries (SQL for Drizzle, MongoDB queries for Mongoose), executes them with proper transactions, and returns raw database results [AdapterQuery → DatabaseDocument]
  5. Run Lifecycle Hooks — HookRunner executes user-defined hooks (beforeCreate, afterRead, etc.) at operation boundaries, allowing custom validation, data transformation, and side effects like sending emails or updating external services [DatabaseDocument → DatabaseDocument]
  6. Handle File Uploads — For upload-enabled collections, StorageAdapter processes file buffers, stores them via configured provider (S3, local filesystem), generates serving URLs, and saves metadata to the database [StorageFile → DatabaseDocument]
  7. Format API Response — Response formatters transform DatabaseDocument results into JSON responses, applying field-level access control, population of relationships, and locale-specific data for internationalized content [DatabaseDocument]

Data Models

The data structures that flow between stages — the contracts that hold the system together.

PayloadConfig packages/payload/src/config/types.ts
Configuration object with collections: CollectionConfig[], globals: GlobalConfig[], db: DatabaseAdapter, admin: AdminConfig, and plugins: Plugin[] defining the entire CMS structure
Loaded at startup from user's payload.config.ts, validated and transformed into runtime configuration, then used to generate database schemas, API routes, and admin UI
CollectionConfig packages/payload/src/collections/config/types.ts
Collection definition with slug: string, fields: Field[], access: AccessControl, hooks: Hooks, upload?: UploadConfig defining content types
Defined in config files, processed into database tables/collections, generates CRUD endpoints and admin forms
DatabaseDocument packages/payload/src/database/types.ts
Generic document structure with id: string|number, createdAt: Date, updatedAt: Date plus user-defined fields from collection configuration
Created through admin UI or API, stored via database adapter, retrieved and transformed for client consumption
AdapterQuery packages/drizzle/src/types.ts
Database query object with where: WhereConditions, sort: SortOptions, limit: number, populate: PopulateOptions translated from REST/GraphQL params
Built from incoming API requests, passed to database adapter for execution, results transformed back to API format
EmailMessage packages/email-nodemailer/src/index.ts
Email payload with to: string, from: string, subject: string, text?: string, html?: string for transactional messaging
Generated by auth hooks and user workflows, processed by email adapter, delivered via configured transport
StorageFile packages/plugin-cloud-storage/src/types.ts
File metadata with filename: string, mimeType: string, size: number, buffer: Buffer for upload processing
Uploaded through admin UI, processed by storage adapter, metadata saved to media collections

Hidden Assumptions

Things this code relies on but never validates. These are the things that cause silent failures when the system changes.

critical Domain guarded

All safe string values match SAFE_STRING_REGEX pattern and any value not matching this regex is dangerous for SQL injection

If this fails: If SAFE_STRING_REGEX is too restrictive, legitimate user data gets rejected with 400 errors. If too permissive, SQL injection vulnerabilities slip through the sanitization

packages/drizzle/src/postgres/createJSONQuery/index.ts:sanitizeValue
critical Shape unguarded

pathSegments array always has at least one element and pathSegments[0] contains the root field name

If this fails: If pathSegments is empty, pathSegments.slice(1) works but fullPath becomes '$[*]' and pathSegments.length === 1 check fails, generating malformed JSON path queries

packages/drizzle/src/postgres/createJSONQuery/index.ts:createJSONQuery
warning Contract unguarded

findMigrationDir function returns a valid directory path that exists and is writable for migration files

If this fails: If migration directory doesn't exist or lacks write permissions, adapter initialization silently continues but migration operations fail later with filesystem errors

packages/db-postgres/src/index.ts:adapter
critical Temporal unguarded

The Promise resolution/rejection callbacks (resolveInitializing/rejectInitializing) will be called exactly once during adapter initialization

If this fails: If initialization code paths don't call these callbacks, API requests hang forever waiting for the adapter to be ready

packages/db-postgres/src/index.ts:initializing
warning Environment weakly guarded

drizzle-kit is available as a runtime dependency when migration operations are called

If this fails: Migration commands fail with module not found errors if drizzle-kit is only installed as devDependency or missing entirely

packages/db-postgres/src/index.ts:requireDrizzleKit
warning Scale unguarded

Arrays passed to 'in'/'not_in' operators have reasonable length that won't exceed PostgreSQL's expression limits

If this fails: Very large arrays generate massive OR/AND chains that exceed PostgreSQL's maximum expression depth, causing query compilation errors

packages/drizzle/src/postgres/createJSONQuery/index.ts:createJSONQuery
critical Domain weakly guarded

sanitizePathSegment function properly escapes all path segment characters that have special meaning in PostgreSQL JSONPath expressions

If this fails: If path segments contain unescaped JSONPath metacharacters like $, @, ?, query syntax breaks or behaves unexpectedly

packages/drizzle/src/postgres/createJSONQuery/index.ts:sanitizePathSegment
warning Shape unguarded

Upload configuration imageSizes array contains objects with exactly 'name', 'height', and 'width' properties of correct types

If this fails: If imageSize objects have wrong property names, missing dimensions, or non-numeric sizes, file upload processing fails or generates broken image variants

test/admin-bar/collections/Media/index.ts:MediaCollection
warning Contract unguarded

afterCreateConnection callback, if provided, completes successfully and doesn't throw exceptions during database initialization

If this fails: If the callback throws errors, MongoDB adapter initialization fails without clear error messages about which custom logic caused the failure

packages/db-mongodb/src/index.ts:Args.afterCreateConnection
warning Environment unguarded

The dist/index.js file exists and exports a main function when the CLI binary executes

If this fails: If TypeScript compilation fails or output directory changes, the CLI command fails with module resolution errors

packages/create-payload-app/bin/cli.js

System Behavior

How the system operates at runtime — where data accumulates, what loops, what waits, and what controls what.

Data Pools

Database Collections (database)
Primary data store where all documents, users, globals, and media metadata accumulate, organized by collection schemas with relationships and indexes
Configuration Registry (in-memory)
Runtime registry holding collection configs, global configs, plugin configurations, and field schemas that drive system behavior
File Storage (file-store)
External storage systems (S3, GCS, local filesystem) that accumulate uploaded files and media assets with URL-based access
Auth Sessions (cache)
JWT tokens and session data that accumulate during user authentication and maintain login state across requests

Feedback Loops

Delays

Control Points

Technology Stack

TypeScript (runtime)
Provides type safety across the entire system, from configuration validation to API response typing and database schema generation
Next.js (framework)
Powers the admin UI as a React application and provides the integration layer for embedding Payload in existing Next.js projects
React (framework)
Renders the admin interface components, forms, tables, and dashboard elements with dynamic UI generation from configurations
Drizzle ORM (database)
Provides SQL database abstraction, query building, schema management, and migrations for PostgreSQL and SQLite adapters
Mongoose (database)
Handles MongoDB operations, schema validation, and document modeling for the MongoDB database adapter
GraphQL (library)
Auto-generates GraphQL schemas and resolvers from Payload configurations, enabling GraphQL API access to collections
Lexical (library)
Provides rich text editing capabilities through Meta's extensible rich text framework for content fields
Nodemailer (library)
Handles transactional email delivery for authentication workflows and user notifications through various SMTP providers
Turbo (build)
Manages the monorepo build system, coordinating package builds, caching, and dependency management across 132 packages
Vitest (testing)
Provides test runner and assertion framework for unit and integration testing across all packages in the monorepo

Key Components

Package Structure

payload (app)
The core CMS engine providing collections, fields, authentication, hooks, and the configuration system that orchestrates all other components.
next (library)
Next.js integration layer that embeds Payload admin UI and API routes into existing Next.js applications.
ui (library)
React component library providing the admin interface components, forms, tables, and dashboard elements.
create-payload-app (tooling)
CLI tool for scaffolding new Payload projects from templates with database setup and configuration.
sdk (library)
TypeScript client SDK for making type-safe API calls to Payload backends from frontend applications.
graphql (library)
Generates GraphQL schema and resolvers from Payload collection configurations for GraphQL API access.
drizzle (library)
Database abstraction layer providing CRUD operations, migrations, and query building for SQL databases.
db-mongodb (library)
MongoDB adapter implementing Payload's database interface using Mongoose for document operations.
db-postgres (library)
PostgreSQL adapter using Drizzle ORM to implement Payload's database operations for relational data.
richtext-lexical (library)
Rich text editor integration using Meta's Lexical framework for structured content editing.
storage-s3 (library)
File storage adapter for Amazon S3 and S3-compatible services handling uploads and media management.
plugin-ecommerce (library)
E-commerce plugin adding product catalogs, shopping cart functionality, and order management collections.

Explore the interactive analysis

See the full architecture map, data flow, and code patterns visualization.

Analyze on CodeSea

Compare payload

Related Fullstack Repositories

Frequently Asked Questions

What is payload used for?

Builds TypeScript fullstack applications with instant backend APIs and admin panels using Next.js payloadcms/payload is a 10-component fullstack written in TypeScript. Data flows through 7 distinct pipeline stages. The codebase contains 6311 files.

How is payload architected?

payload is organized into 6 architecture layers: Configuration & Core, Database Adapters, API & Integration, UI & Admin, and 2 more. Data flows through 7 distinct pipeline stages. This layered structure keeps concerns separated and modules independent.

How does data flow through payload?

Data moves through 7 stages: Load Configuration → Generate Database Schema → Process API Request → Execute Database Operation → Run Lifecycle Hooks → .... Data flows through Payload in multiple patterns: Configuration-driven setup loads user configs and generates database schemas and API routes. Request processing parses incoming HTTP/GraphQL requests, applies access control and validation, executes database operations through adapters, runs hooks, and returns formatted responses. Content creation flows from admin UI forms through validation, hooks, storage adapters for files, and database persistence. The system maintains type safety throughout by generating TypeScript types from configurations. This pipeline design reflects a complex multi-stage processing system.

What technologies does payload use?

The core stack includes TypeScript (Provides type safety across the entire system, from configuration validation to API response typing and database schema generation), Next.js (Powers the admin UI as a React application and provides the integration layer for embedding Payload in existing Next.js projects), React (Renders the admin interface components, forms, tables, and dashboard elements with dynamic UI generation from configurations), Drizzle ORM (Provides SQL database abstraction, query building, schema management, and migrations for PostgreSQL and SQLite adapters), Mongoose (Handles MongoDB operations, schema validation, and document modeling for the MongoDB database adapter), GraphQL (Auto-generates GraphQL schemas and resolvers from Payload configurations, enabling GraphQL API access to collections), and 4 more. This broad technology surface reflects a mature project with many integration points.

What system dynamics does payload have?

payload exhibits 4 data pools (Database Collections, Configuration Registry), 4 feedback loops, 5 control points, 4 delays. The feedback loops handle polling and recursive. These runtime behaviors shape how the system responds to load, failures, and configuration changes.

What design patterns does payload use?

5 design patterns detected: Adapter Pattern, Plugin Architecture, Configuration-Driven Development, Hook System, Monorepo Package Architecture.

How does payload compare to alternatives?

CodeSea has side-by-side architecture comparisons of payload with strapi, directus. These comparisons show tech stack differences, pipeline design, system behavior, and code patterns. See the comparison pages above for detailed analysis.

Analyzed on April 20, 2026 by CodeSea. Written by .