Choosing an Apollo Server package
Use the right package for your project
⚠️ As of 22 October 2024, Apollo Server 3 is officially end-of-life.
Apollo Server is distributed as a collection of different packages for different environments and web frameworks. You can choose which package to use based on your project.
Which package should I use?
In most cases, you should get started with the "batteries-included" apollo-server
package.
If your project has specific requirements, we recommend choosing a package based on this flowchart:
After you choose a package, see its basic usage.
All supported packages
Name | Description |
---|---|
apollo-server | This "batteries-included" package helps you get started quickly. Recommended for all projects that don't require serverless support or a particular Node.js framework (such as hapi).Because it sets helpful defaults, this library is also less configurable than other Apollo Server libraries. Complex projects might eventually need to swap it out for apollo-server-express (this process is straightforward). |
apollo-server-express | This library enables you to attach Apollo Server to an Express server.The apollo-server library uses this library under the hood. Projects that start by using apollo-server sometimes need to swap it out for apollo-server-express when additional configuration is required. |
Serverless-specific packages | The following libraries are available for running in a particular serverless environment:
|
Framework-specific packages | The following libraries are available for integrating Apollo Server with a particular Node.js framework:Use each of these libraries if and only if you're integrating with the corresponding framework. |
Swapping out apollo-server
After you get up and running with the "batteries-included" apollo-server
package, you might want to configure its HTTP behavior in ways that this package doesn't support. For example, you might want to run some middleware before processing GraphQL requests, or you might want to serve other endpoints from the same server.
In this case, we recommend you swap out apollo-server
for apollo-server-express
(unless you are confident that you want to use a different Node.js framework). This change requires only a few lines and has a minimal effect on your server's existing behavior (apollo-server
uses apollo-server-express
under the hood).
We recommend Express because it's the most popular Node.js web framework, and it integrates well with many other popular libraries. It does have its limitations (for example, Express async support is not built around
Promise
s andasync
functions), but backward incompatible changes to the framework are rarer than in newer libraries.
Example
Let's say our apollo-server
implementation uses the following code:
1import { ApolloServer } from "apollo-server";
2import {
3 ApolloServerPluginLandingPageLocalDefault
4} from "apollo-server-core";
5
6async function startApolloServer(typeDefs, resolvers) {
7 const server = new ApolloServer({
8 typeDefs,
9 resolvers,
10 csrfPrevention: true,
11 cache: "bounded",
12 plugins: [
13 ApolloServerPluginLandingPageLocalDefault({ embed: true }),
14 ],
15 });
16 const { url } = await server.listen();
17 console.log(`🚀 Server ready at ${url}`);
18}
To swap this out for apollo-server-express
, we first install the following required packages:
1npm install apollo-server-express apollo-server-core express graphql
We can (and should) also uninstall apollo-server
.
Next, we can modify our code to match the following:
1import { ApolloServer } from 'apollo-server-express';
2import {
3 ApolloServerPluginDrainHttpServer,
4 ApolloServerPluginLandingPageLocalDefault,
5} from 'apollo-server-core';
6import express from 'express';
7import http from 'http';
8
9async function startApolloServer(typeDefs, resolvers) {
10 // Required logic for integrating with Express
11 const app = express();
12 // Our httpServer handles incoming requests to our Express app.
13 // Below, we tell Apollo Server to "drain" this httpServer,
14 // enabling our servers to shut down gracefully.
15 const httpServer = http.createServer(app);
16
17 // Same ApolloServer initialization as before, plus the drain plugin
18 // for our httpServer.
19 const server = new ApolloServer({
20 typeDefs,
21 resolvers,
22 csrfPrevention: true,
23 cache: 'bounded',
24 plugins: [
25 ApolloServerPluginDrainHttpServer({ httpServer }),
26 ApolloServerPluginLandingPageLocalDefault({ embed: true }),
27 ],
28 });
29
30 // More required logic for integrating with Express
31 await server.start();
32 server.applyMiddleware({
33 app,
34
35 // By default, apollo-server hosts its GraphQL endpoint at the
36 // server root. However, *other* Apollo Server packages host it at
37 // /graphql. Optionally provide this to match apollo-server.
38 path: '/'
39 });
40
41 // Modified server startup
42 await new Promise<void>(resolve => httpServer.listen({ port: 4000 }, resolve));
43 console.log(`🚀 Server ready at http://localhost:4000${server.graphqlPath}`);
44}
Package conventions
Each Apollo Server package exports an ApolloServer
class. The APIs for these classes are similar but not identical.
All Apollo Server packages depend on apollo-server-core
, which contains the code that's shared by all integrations. Certain symbols, such as built-in plugins, are imported directly from apollo-server-core
instead of from a particular package.
All Apollo Server packages (and apollo-server-core
) are published to npm with the same version number, even if certain packages have no changes for a particular version. This makes it more straightforward to discuss a particular version of Apollo Server without needing to specify a package name.
Certain support libraries (such as apollo-server-types
and apollo-server-plugin-base
) use their own versioning and are published only when they change or one of their dependencies changes.
Common options
Most Apollo Server packages require calling a method named applyMiddleware
, getMiddleware
, or createHandler
(depending on the package). These methods accept a (mostly) common set of options (not every package accepts every option).
For descriptions of these options, see the API reference.
The set of common options supported by each package is listed under Basic usage.
Basic usage
The sections below demonstrate how to initialize an ApolloServer
instance with each package. More details are available in each package's README.
Each section also lists the options supported by each package's applyMiddleware
or getMiddleware
or createHandler
function. Learn more about how these options work in the ApolloServer
API reference.
apollo-server
apollo-server
is the "batteries-included" Apollo Server package. It enables you to spin up a GraphQL server without thinking about web frameworks or URLs or middleware, and its main entry point (listen
) is an async
function instead of a callback-based function.
1npm install apollo-server graphql
1import { ApolloServer } from 'apollo-server';
2
3async function startApolloServer(typeDefs, resolvers) {
4 const server = new ApolloServer({
5 typeDefs,
6 resolvers,
7 csrfPrevention: true,
8 cache: 'bounded',
9 plugins: [
10 ApolloServerPluginLandingPageLocalDefault({ embed: true }),
11 ],
12 });
13 const { url } = await server.listen();
14 console.log(`🚀 Server ready at ${url}`);
15}
Although apollo-server
helps you get started quickly, you can't configure its behavior as much as you can other Apollo Server packages. For example, you can't serve other endpoints from the same HTTP server.
If you want to do something with your server that isn't supported by apollo-server
, you can swap to apollo-server-express
.
apollo-server-express
apollo-server-express
is the Apollo Server package for Express, the most popular Node.js web framework. It enables you to attach a GraphQL server to an existing Express server.
The batteries-included apollo-server
library uses apollo-server-express
under the hood. If you start with apollo-server
and later need to modify how it serves over HTTP, you can swap apollo-server
to apollo-server-express
.
The following example is roughly equivalent to the apollo-server
example above.
1npm install apollo-server-express apollo-server-core express graphql
1import { ApolloServer } from 'apollo-server-express';
2import {
3 ApolloServerPluginDrainHttpServer,
4 ApolloServerPluginLandingPageLocalDefault,
5} from 'apollo-server-core';
6import express from 'express';
7import http from 'http';
8
9async function startApolloServer(typeDefs, resolvers) {
10 const app = express();
11 const httpServer = http.createServer(app);
12 const server = new ApolloServer({
13 typeDefs,
14 resolvers,
15 csrfPrevention: true,
16 cache: 'bounded',
17 plugins: [
18 ApolloServerPluginDrainHttpServer({ httpServer }),
19 ApolloServerPluginLandingPageLocalDefault({ embed: true }),
20 ],
21 });
22 await server.start();
23 server.applyMiddleware({ app });
24 await new Promise<void>(resolve => httpServer.listen({ port: 4000 }, resolve));
25 console.log(`🚀 Server ready at http://localhost:4000${server.graphqlPath}`);
26}
You must await server.start()
before calling server.applyMiddleware
. You can add other middleware to app
before or after calling applyMiddleware
.
You can call server.getMiddleware
instead of server.applyMiddleware
if you want to do something with the middleware function besides apply it directly to your app. (server.applyMiddleware({ app, ...rest })
is shorthand for app.use(server.getMiddleware(rest))
.)
applyMiddleware
(along with getMiddleware
) accepts the following common options:
path
cors
bodyParserConfig
onHealthCheck
disableHealthCheck
apollo-server-fastify
apollo-server-fastify
is the GraphQL server for Fastify, a Node.js web framework. Apollo Server 3 supports Fastify v3.
The following example is roughly equivalent to the apollo-server
example above.
1npm install apollo-server-fastify apollo-server-core fastify graphql
1import { ApolloServer } from 'apollo-server-fastify';
2import {
3 ApolloServerPluginDrainHttpServer,
4 ApolloServerPluginLandingPageLocalDefault,
5} from 'apollo-server-core';
6import { ApolloServerPlugin } from 'apollo-server-plugin-base';
7import fastify, { FastifyInstance } from 'fastify';
8
9function fastifyAppClosePlugin(app: FastifyInstance): ApolloServerPlugin {
10 return {
11 async serverWillStart() {
12 return {
13 async drainServer() {
14 await app.close();
15 },
16 };
17 },
18 };
19}
20
21async function startApolloServer(typeDefs, resolvers) {
22 const app = fastify();
23 const server = new ApolloServer({
24 typeDefs,
25 resolvers,
26 csrfPrevention: true,
27 cache: 'bounded',
28 plugins: [
29 fastifyAppClosePlugin(app),
30 ApolloServerPluginDrainHttpServer({ httpServer: app.server }),
31 ApolloServerPluginLandingPageLocalDefault({ embed: true }),
32 ],
33 });
34
35 await server.start();
36 app.register(server.createHandler());
37 await app.listen(4000);
38 console.log(`🚀 Server ready at http://localhost:4000${server.graphqlPath}`);
39}
You must await server.start()
before calling server.createHandler
. You can call other functions on app
before or after calling createHandler
.
createHandler
accepts the following common options:
path
cors
onHealthCheck
disableHealthCheck
See this issue for details about draining Fastify servers. The pattern suggested here isn't perfect; we look forward to suggestions from Fastify users.
apollo-server-hapi
apollo-server-hapi
is the GraphQL server for hapi, a Node.js web framework. Apollo Server 3 is only tested with @hapi/hapi
v20.1.2 and later (the minimum version that supports Node.js 16).
The following example is roughly equivalent to the apollo-server
example above.
1npm install apollo-server-hapi @hapi/hapi graphql
1import {
2 ApolloServer,
3 ApolloServerPluginStopHapiServer
4} from 'apollo-server-hapi';
5import {
6 ApolloServerPluginLandingPageLocalDefault,
7} from 'apollo-server-core';
8import Hapi from '@hapi/hapi';
9
10async function startApolloServer(typeDefs, resolvers) {
11 const app = Hapi.server({ port: 4000 });
12 const server = new ApolloServer({
13 typeDefs,
14 resolvers,
15 csrfPrevention: true,
16 cache: 'bounded',
17 plugins: [
18 ApolloServerPluginStopHapiServer({ hapiServer: app }),
19 ApolloServerPluginLandingPageLocalDefault({ embed: true }),
20 ],
21 });
22
23 await server.start();
24 await server.applyMiddleware({ app });
25 await app.start();
26}
You must await server.start()
before calling server.applyMiddleware
. You can call other functions on app
before or after calling applyMiddleware
.
applyMiddleware
accepts the following common options:
path
route
cors
onHealthCheck
disableHealthCheck
apollo-server-koa
apollo-server-koa
is the GraphQL server for Koa, a Node.js web framework.
The following example is roughly equivalent to the apollo-server
example above.
1npm install apollo-server-koa apollo-server-core koa graphql
1import { ApolloServer } from 'apollo-server-koa';
2import {
3 ApolloServerPluginDrainHttpServer,
4 ApolloServerPluginLandingPageLocalDefault,
5} from 'apollo-server-core';
6import Koa from 'koa';
7import http from 'http';
8
9async function startApolloServer(typeDefs, resolvers) {
10 const httpServer = http.createServer();
11 const server = new ApolloServer({
12 typeDefs,
13 resolvers,
14 csrfPrevention: true,
15 cache: 'bounded',
16 plugins: [
17 ApolloServerPluginDrainHttpServer({ httpServer }),
18 ApolloServerPluginLandingPageLocalDefault({ embed: true }),
19 ],
20 });
21
22 await server.start();
23 const app = new Koa();
24 server.applyMiddleware({ app });
25 httpServer.on('request', app.callback());
26 await new Promise<void>(resolve => httpServer.listen({ port: 4000 }, resolve));
27 console.log(`🚀 Server ready at http://localhost:4000${server.graphqlPath}`);
28 return { server, app };
29}
You must await server.start()
before calling server.applyMiddleware
. You can call other functions on app
before or after calling applyMiddleware
.
You can call server.getMiddleware
instead of server.applyMiddleware
if you want to do something with the middleware function besides apply it directly to your app. (server.applyMiddleware({ app, ...rest })
is shorthand for app.use(server.getMiddleware(rest))
.)
applyMiddleware
(along with getMiddleware
) accepts the following common options:
path
cors
bodyParserConfig
onHealthCheck
disableHealthCheck
apollo-server-micro
apollo-server-micro
is the GraphQL server for Micro, a Node.js web framework.
The following example is roughly equivalent to the apollo-server
example above. You should put this code in a file called index.js
in order for the micro
CLI to find it.
1npm install apollo-server-micro micro graphql
1import { ApolloServer } from 'apollo-server-micro';
2import { ApolloServerPluginLandingPageLocalDefault } from 'apollo-server-core';
3
4const server = new ApolloServer({
5 typeDefs,
6 resolvers,
7 csrfPrevention: true,
8 cache: 'bounded',
9 plugins: [
10 ApolloServerPluginLandingPageLocalDefault({ embed: true }),
11 ],
12});
13
14module.exports = server.start().then(() => server.createHandler());
Then run the web server with npx micro
.
createHandler
accepts the following common options:
path
onHealthCheck
disableHealthCheck
Note that apollo-server-micro
does not have a built-in way of setting CORS headers.
We do not have a recommended
drainServer
implementation forapollo-server-micro
. If you useapollo-server-micro
, feel free to contribute one!
apollo-server-lambda
apollo-server-lambda
is the GraphQL server for AWS Lambda, Amazon's serverless compute service.
This package is a layer around apollo-server-express
, which uses the @vendia/serverless-express
package to translate Lambda events into Express requests. (This package is not related to the Serverless framework.) It supports API Gateway and ALB.
The following example is roughly equivalent to the apollo-server
example above.
1npm install apollo-server-lambda graphql