apollo-server-express, apollo-server-fastify, express-graphql, graphql-yoga, and mercurius are all libraries for building GraphQL servers in Node.js, each designed to integrate with a specific HTTP framework or provide a standalone solution. They enable developers to define GraphQL schemas, resolvers, and middleware to handle incoming queries and mutations over HTTP. While some are tightly coupled to Express or Fastify, others offer framework-agnostic or built-in server capabilities with modern features like subscriptions, persisted queries, and developer tooling.
Building a GraphQL server in Node.js gives you many options, but they differ significantly in architecture, maintenance status, and integration depth. Let’s compare apollo-server-express, apollo-server-fastify, express-graphql, graphql-yoga, and mercurius based on real-world engineering needs.
Before diving into features, check what’s actively maintained:
express-graphql is officially deprecated as of 2023. The maintainers recommend migrating to alternatives. Do not use in new projects.apollo-server-express and apollo-server-fastify are part of Apollo Server v3, which is in maintenance mode. Apollo Server v4+ uses a single @apollo/server package with framework adapters. These older packages still work but lack new features.graphql-yoga and mercurius are actively developed and recommended for new projects.apollo-server-express (v3)Requires Express app + Apollo middleware.
import express from 'express';
import { ApolloServer } from 'apollo-server-express';
import { typeDefs, resolvers } from './schema.js';
const app = express();
const server = new ApolloServer({ typeDefs, resolvers });
await server.start();
server.applyMiddleware({ app });
app.listen(4000);
apollo-server-fastify (v3)Similar pattern, but for Fastify.
import Fastify from 'fastify';
import { ApolloServer } from 'apollo-server-fastify';
import { typeDefs, resolvers } from './schema.js';
const fastify = Fastify();
const server = new ApolloServer({ typeDefs, resolvers });
await server.start();
server.applyMiddleware({ app: fastify });
await fastify.listen({ port: 4000 });
express-graphql (deprecated)Minimal setup, but no longer updated.
import express from 'express';
import { graphqlHTTP } from 'express-graphql';
import { schema } from './schema.js';
const app = express();
app.use('/graphql', graphqlHTTP({ schema, graphiql: true }));
app.listen(4000);
graphql-yogaWorks standalone or with any HTTP framework. Zero-config GraphiQL included.
import { createYoga } from 'graphql-yoga';
import { createServer } from 'http';
import { schema } from './schema.js';
const yoga = createYoga({ schema });
const server = createServer(yoga);
server.listen(4000);
Or with Express:
import express from 'express';
const app = express();
app.use('/graphql', yoga);
mercuriusFastify plugin — registers as a decorator.
import Fastify from 'fastify';
import mercurius from 'mercurius';
import { schema } from './schema.js';
const fastify = Fastify();
await fastify.register(mercurius, {
schema,
graphiql: true
});
await fastify.listen({ port: 4000 });
apollo-server-express / apollo-server-fastify: Shallow wrappers. Apollo handles GraphQL logic; HTTP framework just routes requests. You lose access to framework-specific features (e.g., Fastify hooks) inside resolvers unless manually passed.
mercurius: Deep Fastify integration. You can access request and reply objects in resolvers, use Fastify hooks for auth/validation, and leverage Fastify’s logging and error handling natively.
// In mercurius resolver
const resolvers = {
Query: {
me: (parent, args, context) => {
// context.reply is the Fastify reply object
return getUser(context.reply.request.headers.authorization);
}
}
};
graphql-yoga: Framework-agnostic by design. When used with Express or Fastify, it acts as middleware. Context is customizable but doesn’t auto-inject framework objects unless configured.const yoga = createYoga({
schema,
context: ({ request }) => ({
authHeader: request.headers.get('authorization')
})
});
express-graphql: No subscription support.subscriptions-transport-ws.mercurius: Built-in WebSocket subscriptions using ws or uWebSockets.js. Simple configuration.await fastify.register(mercurius, {
schema,
subscription: true
});
graphql-yoga: Includes subscription support out of the box with graphql-ws (modern protocol). No extra dependencies needed.const yoga = createYoga({ schema, graphqlEndpoint: '/graphql' });
// Subscriptions enabled automatically at same endpoint
GraphiQL / Playground:
express-graphql: Basic GraphiQL.graphql-yoga: Built-in GraphiQL with offline support.mercurius: GraphiQL or GraphQL Playground toggle.Error Handling:
mercurius maps Fastify errors to GraphQL errors.graphql-yoga includes detailed error masking and formatting.mercurius leverages Fastify’s high-performance JSON parsing and low-overhead routing. Ideal for high-throughput APIs.graphql-yoga is optimized for both serverful and serverless environments, with lazy loading and minimal cold starts.mercurius: Integrates with Fastify plugins (e.g., rate limiting, JWT auth).graphql-yoga: Middleware-based architecture — easy to add custom logic via onRequest, onResult, etc.const yoga = createYoga({
schema,
plugins: [
{
onRequest: ({ request, endResponse }) => {
if (!request.headers.get('x-api-key')) {
endResponse(new Response('Unauthorized', { status: 401 }));
}
}
}
]
});
| Package | Status | Best For |
|---|---|---|
express-graphql | ❌ Deprecated | Legacy migration only |
apollo-server-express | ⚠️ Maintenance mode | Existing Apollo + Express apps |
apollo-server-fastify | ⚠️ Maintenance mode | Existing Apollo + Fastify apps |
graphql-yoga | ✅ Active | New projects, multi-framework, serverless |
mercurius | ✅ Active | Fastify-native, high-performance APIs |
graphql-yoga.mercurius.@apollo/server (not the old adapter packages).express-graphql.Choose based on your HTTP framework strategy, not just GraphQL features — the server layer affects logging, monitoring, auth, and deployment more than you might expect.
Choose apollo-server-express if you're already using Express and need a mature, well-documented GraphQL integration with Apollo's ecosystem (e.g., Apollo Studio, federated tracing). It’s ideal for teams invested in the Apollo platform and requiring enterprise-grade observability and schema management. However, note that Apollo Server v4+ is now framework-agnostic, and this package is effectively deprecated in favor of the unified @apollo/server with Express adapter.
Choose apollo-server-fastify if your backend is built on Fastify and you want Apollo Server integration. Like its Express counterpart, it’s now largely superseded by the newer @apollo/server with Fastify plugin support. Only consider this if maintaining legacy Apollo Server v3 code; new projects should use the official Fastify plugin from @apollo/server instead.
Do not choose express-graphql for new projects — it is officially deprecated as of 2023. The package has not been updated in years and lacks modern GraphQL features like subscriptions, persisted queries, and performance optimizations. Migrate existing usage to alternatives like graphql-yoga or Apollo Server.
Choose graphql-yoga if you want a modern, batteries-included GraphQL server that works out of the box with minimal setup. It supports Express, Fastify, Node.js native HTTP, and serverless environments, includes built-in GraphiQL, subscriptions, file uploads, and schema stitching. It’s ideal for greenfield projects prioritizing developer experience, simplicity, and cross-platform compatibility without vendor lock-in.
Choose mercurius if you’re building a high-performance GraphQL API on Fastify and need deep integration with Fastify’s ecosystem (e.g., hooks, decorators, logging). It offers excellent support for subscriptions, persisted queries, and caching, and is actively maintained. Best suited for teams standardizing on Fastify who want a lightweight, performant GraphQL layer without Apollo dependencies.
This is the Express integration of Apollo 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.
A full example of how to use apollo-server-express can be found in the docs.
Before Apollo Server 3, we officially supported using this package with connect as well. connect is an older framework that express evolved from. For now, we believe that this package is still compatible with connect and we even run tests against connect, but we may choose to break this compatibility at some point without a major version bump. If you rely on the ability to use Apollo Server with connect, you may wish to make your own integration.
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!