Does Fastify Work With Sanity?

Fully CompatibleLast verified: 2026-02-26

Fastify and Sanity work together seamlessly—use Fastify as your backend API server to fetch and serve content from Sanity's headless CMS.

Quick Facts

Compatibility
full
Setup Difficulty
Easy
Official Integration
No — community maintained
Confidence
high
Minimum Versions
Fastify: 3.0.0

How Fastify Works With Sanity

Fastify is an excellent choice for building APIs that consume Sanity content. The pattern is straightforward: use Fastify's lightweight routing to create endpoints that query Sanity's Content Delivery Network via the `@sanity/client` library. Sanity provides real-time APIs and webhooks, making it simple to build dynamic backends that respond to content changes. Fastify's low overhead and plugin architecture make it particularly suited for this—you can build a performant content API in minutes. The developer experience is smooth: define Sanity schemas in your CMS, install the client SDK, and start querying from your Fastify routes. You'll typically wrap Sanity queries in route handlers, optionally caching results with Fastify's built-in caching or Redis integration. This combination scales well from simple blogs to complex multi-tenant applications.

Best Use Cases

Headless CMS backend serving JSON to frontend frameworks (Next.js, SvelteKit, Nuxt)
Real-time content APIs with webhook-triggered cache invalidation in Fastify
Multi-language content delivery with Sanity's i18n support and Fastify routing
JAMstack applications where Fastify handles dynamic content queries Sanity can't pre-render

Quick Setup

bash
npm install fastify @sanity/client dotenv
typescript
import Fastify from 'fastify';
import { createClient } from '@sanity/client';

const fastify = Fastify();
const sanity = createClient({
  projectId: process.env.SANITY_PROJECT_ID,
  dataset: process.env.SANITY_DATASET,
  apiVersion: '2024-01-01',
  useCdn: true,
});

fastify.get('/posts', async (request, reply) => {
  const posts = await sanity.fetch(
    `*[_type == "post"] | order(publishedAt desc)[0...10]`
  );
  return posts;
});

fastify.get('/posts/:slug', async (request, reply) => {
  const { slug } = request.params as { slug: string };
  const post = await sanity.fetch(
    `*[_type == "post" && slug.current == $slug][0]`,
    { slug }
  );
  return post || reply.notFound();
});

await fastify.listen({ port: 3000 });

Known Issues & Gotchas

warning

Sanity's Content Delivery API has rate limits (500 req/min on free tier)

Fix: Implement caching in Fastify using decorators or a cache plugin. Consider upgrading Sanity plan for production traffic.

info

CORS headers needed if frontend is on different origin

Fix: Use @fastify/cors plugin: `await fastify.register(require('@fastify/cors'))`

warning

Stale content if not handling webhooks properly

Fix: Set up Sanity webhooks to POST to Fastify endpoints that invalidate cached content on publish

Alternatives

  • Next.js API routes + Sanity (tighter integration, built-in caching, but less flexible)
  • Express.js + Sanity (more ecosystem plugins, heavier framework overhead)
  • Remix + Sanity (better data loading patterns, but opinionated framework)

Resources

Related Compatibility Guides

Explore more compatibility guides