apollo-server-fastify and mercurius are both GraphQL server implementations designed to run on top of the Fastify web framework. apollo-server-fastify is an official integration package from the Apollo GraphQL team that connects the standard Apollo Server engine to Fastify, allowing developers to use familiar Apollo features within a high-performance HTTP server. mercurius, on the other hand, is a native GraphQL adapter built specifically for Fastify by the Fastify community. It leverages Fastify's internal lifecycle hooks and plugin architecture directly, aiming for lower overhead and tighter integration than the generic Apollo adapter. While both enable GraphQL APIs, they differ significantly in how they handle schema definition, context propagation, and subscription management.
When building GraphQL services in Node.js, Fastify has become the go-to web framework for developers who need high throughput and low latency. However, choosing the right GraphQL layer on top of Fastify is a critical architectural decision. The two main contenders are apollo-server-fastify (the official Apollo integration) and mercurius (the native Fastify plugin). While both get a GraphQL API running, they take fundamentally different approaches to architecture, performance, and maintenance.
The core difference lies in how these packages integrate with Fastify.
apollo-server-fastify acts as a bridge. It runs the standard Apollo Server engine inside a Fastify route handler. This means you get the full Apollo experience, but it comes with an extra layer of abstraction. The request flows through Fastify, gets handed off to Apollo, processed, and then returned. This can introduce slight overhead and limits how deeply you can tap into Fastify's internal lifecycle.
// apollo-server-fastify: Wrapping Apollo inside Fastify
import Fastify from 'fastify';
import { ApolloServer } from '@apollo/server';
import { fastifyApolloDrain, fastifyApolloHandler } from '@apollo/server-fastify';
const fastify = Fastify();
const server = new ApolloServer({ typeDefs, resolvers });
await server.start();
// Registers a route handler that delegates to Apollo
fastify.post('/graphql', fastifyApolloHandler(server));
fastify.addHook('onClose', fastifyApolloDrain(server));
mercurius is built from the ground up as a Fastify plugin. It doesn't wrap an external engine; instead, it implements the GraphQL specification directly using Fastify's primitives. This allows it to hook directly into Fastify's request lifecycle, decoration system, and error handling without context switching.
// mercurius: Native Fastify Plugin
import Fastify from 'fastify';
import mercurius from 'mercurius';
const app = Fastify();
app.register(mercurius, {
schema: `
type Query {
add(x: Int, y: Int): Int
}
`,
resolvers: {
Query: {
add: async (_, { x, y }) => x + y
}
}
});
Before diving into features, there is a crucial factor for new projects. The Apollo Server team has officially deprecated their framework-specific integrations, including apollo-server-fastify.
In their migration guides, Apollo now recommends using their standalone HTTP server (@apollo/server/standalone) or generic middleware patterns. While apollo-server-fastify still functions, it is no longer receiving feature updates, and long-term support is uncertain.
mercurius, maintained by the Fastify core team, is actively developed and follows Fastify's release cadence. For any new project starting today, mercurius is the strategically safer choice to avoid technical debt related to deprecated dependencies.
Because mercurius avoids the abstraction layer of Apollo Server, it generally offers better performance, especially under high load. It parses requests and manages context using Fastify's optimized internal structures.
apollo-server-fastify incurs the cost of the Apollo Server engine's generic request processing pipeline. While often negligible for small apps, this overhead becomes visible in high-concurrency scenarios where every millisecond counts.
// mercurius: Direct access to Fastify request object in context
app.register(mercurius, {
context: (req, reply) => {
// Direct access to Fastify's request and reply
return { user: req.user };
}
});
// apollo-server-fastify: Context mapping required
// You must map Fastify's request to Apollo's context format
fastify.post('/graphql', async (req, reply) => {
// Extra step to translate Fastify context to Apollo context
const context = { user: req.user };
// ... Apollo handles the rest internally
});
Real-time data via GraphQL Subscriptions is a common requirement. The implementation experience differs sharply between the two.
mercurius has subscriptions built directly into the core plugin. It uses Fastify's WebSocket support seamlessly. You just enable the option, and it works.
// mercurius: Subscriptions enabled with a single flag
app.register(mercurius, {
schema,
resolvers,
subscription: true // Enabled natively
});
// Resolver usage
const resolvers = {
Subscription: {
messageAdded: {
subscribe: async function* (source, args, context) {
for await (const msg of context.pubsub.subscribe('MESSAGE_ADDED')) {
yield msg;
}
}
}
}
};
apollo-server-fastify requires additional setup. In older versions of Apollo Server, subscriptions were often handled by a separate library (graphql-subscriptions) and required a distinct WebSocket server instance or complex middleware configuration to coexist with the HTTP server.
// apollo-server-fastify: Historically required separate WS handling
// Often needed a separate express/ws app or complex plugin config
// Modern Apollo Server v4 has shifted subscription patterns significantly,
// making the fastify integration even more complex to configure correctly.
const server = new ApolloServer({
typeDefs,
resolvers,
// Subscription configuration is less direct and often requires
// external WebSocket server management in this integration model
});
apollo-server-fastify shines if you are already using Apollo Studio, managed federation, or specific Apollo plugins for caching and tracing. It speaks the "Apollo language" natively. If your organization standardizes on Apollo tooling, this package reduces friction in reporting and monitoring.
mercurius feels like a natural extension of Fastify. It supports:
// mercurius: Built-in Loaders for batching
app.register(mercurius, {
schema,
resolvers,
loaders: {
User: {
// Automatically batches calls to getUserById
getUserById: async (queries, users) => {
const ids = queries.map(({ obj }) => obj.id);
const dbUsers = await database.findUsers(ids);
return dbUsers;
}
}
}
});
| Feature | apollo-server-fastify | mercurius |
|---|---|---|
| Architecture | Adapter wrapping Apollo Engine | Native Fastify Plugin |
| Maintenance | ⚠️ Deprecated by Apollo Team | ✅ Actively Maintained |
| Performance | Good (Standard Apollo overhead) | Excellent (Native optimization) |
| Subscriptions | Complex / External setup | ✅ Built-in & Simple |
| Data Loading | Requires external DataLoader | ✅ Built-in Loaders |
| Context | Mapped from Fastify | Direct Fastify Request/Reply |
| Ecosystem | Apollo Studio & Plugins | Fastify Community Plugins |
For new projects, the choice is clear: use mercurius.
The deprecation of apollo-server-fastify by the Apollo team signals a shift in their strategy towards standalone servers. Continuing to build on a deprecated integration invites future migration headaches. mercurius not only avoids this risk but also provides a tighter, faster, and more feature-rich experience specifically tailored for Fastify. Its built-in support for subscriptions and loaders reduces the need for third-party dependencies, simplifying your dependency tree.
Only consider apollo-server-fastify if you are maintaining a legacy system that strictly depends on Apollo-specific enterprise features (like Managed Federation v2) and cannot be refactored immediately. Even then, planning a migration to mercurius or the Apollo Standalone server should be a priority.
Choose apollo-server-fastify if your team is already heavily invested in the Apollo ecosystem, relies on specific Apollo Server plugins (like usage reporting or cache control), or needs to share schema logic between different server environments (e.g., switching between Express and Fastify). It is also the safer choice if you require long-term support guarantees from the Apollo organization, though you must accept slightly higher abstraction overhead compared to native solutions.
Choose mercurius if performance is your top priority and you want to fully leverage Fastify's low-latency architecture without the abstraction layer of Apollo Server. It is ideal for teams that prefer a 'Fastify-first' approach, need built-in support for GraphQL subscriptions without extra configuration, or want to use Fastify decorators and hooks directly within their resolvers. Note that as of late 2023, the Apollo Server team has deprecated most framework-specific integrations, making mercurius the more future-proof option for new Fastify projects.
This is the Fastify integration of GraphQL Server. Apollo Server is a community-maintained open-source GraphQL server that works with many Node.js HTTP server frameworks. Read the docs. Read the CHANGELOG.
As of Apollo Server 3, this package supports Fastify v3 only.
A full example of how to use apollo-server-fastify can be found in the docs.
GraphQL Server is built with the following principles in mind:
Anyone is welcome to contribute to GraphQL Server, just read CONTRIBUTING.md, take a look at the roadmap and make your first PR!