Does Fastify Work With Payload CMS?
Fastify can serve as Payload CMS's custom server, but Payload is primarily Express-oriented, requiring manual integration and middleware adaptation.
Quick Facts
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
Quick Setup: Fastify with Payload CMS
npm install fastify payload dotenv expressimport 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
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).
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.
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.
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