Does Fastify Work With Payload CMS?

Partially CompatibleLast verified: 2026-02-26

Fastify can serve as Payload CMS's custom server, but Payload is primarily Express-oriented, requiring manual integration and middleware adaptation.

Quick Facts

Compatibility
partial
Setup Difficulty
Moderate
Official Integration
No — community maintained
Confidence
high
Minimum Versions
Fastify: 4.0.0
Payload CMS: 2.0.0

How Fastify Works With Payload CMS

Payload CMS is built on Express.js and Express middleware patterns by default. However, you can use Fastify as Payload's underlying server by leveraging Payload's plugin system and manually registering routes. The approach involves creating a Fastify instance, initializing Payload without its built-in Express server, and then manually mounting Payload's Express app to Fastify using `fastify-express` adapter. This works but requires more setup than using Express directly. The developer experience is solid once configured, but you lose some of Payload's automatic conventions. Fastify's performance benefits are real—faster request handling and lower memory overhead—making this worthwhile for high-traffic headless CMS setups. However, you'll encounter impedance mismatches with middleware compatibility and debugging can be trickier since Payload's documentation focuses on Express patterns. For pure API usage (querying Payload via REST endpoints), Fastify works seamlessly as a proxy/wrapper layer without deep integration.

Best Use Cases

Building a high-performance headless CMS backend where Fastify's speed advantage justifies integration effort
Creating a custom admin dashboard backend that combines Payload content management with Fastify's lightweight routing
Microservices architecture where Payload CMS is one service behind a Fastify API gateway
Serverless-adjacent deployments requiring minimal overhead with Payload as content source

Quick Setup: Fastify with Payload CMS

bash
npm install fastify payload dotenv express
typescript
import Fastify from 'fastify';
import fastifyExpress from '@fastify/express';
import payload from 'payload';

const app = Fastify();

await app.register(fastifyExpress);

await payload.init({
  secret: process.env.PAYLOAD_SECRET!,
  express: app.express,
  onInit: async () => console.log('Payload initialized'),
});

// Add custom Fastify routes
app.get('/api/health', async () => ({ status: 'ok' }));

await app.listen({ port: 3000 });
console.log('Server running on http://localhost:3000');

Known Issues & Gotchas

warning

Express middleware incompatibility with Fastify's plugin system

Fix: Use `fastify-express` to wrap Express middleware, but test thoroughly. Some complex middleware may not work; consider Fastify equivalents (e.g., fastify-cors instead of cors package).

critical

Payload admin UI routing conflicts when mounting on Fastify

Fix: Serve Payload admin UI separately or use a reverse proxy. Don't try to mount the full Express app directly to Fastify.

warning

Missing Payload built-in features like automatic API route generation

Fix: Manually define routes for collections and globals, or use Payload's REST API as a separate Express service and call it from Fastify.

info

Type safety with TypeScript can be fragmented across frameworks

Fix: Use Payload's TypeScript config and maintain strict types at Fastify integration boundaries.

Alternatives

  • Express + Payload CMS (official, zero friction, slightly slower)
  • Next.js with Payload CMS (full-stack, built-in SSR, heavier)
  • Nest.js + Payload CMS (more structured, heavier learning curve)

Resources

Related Compatibility Guides

Explore more compatibility guides