Docs
Launch GraphOS Studio
Apollo Server 3 is officially deprecated, with end-of-life scheduled for 22 October 2024. Learn more about upgrading to a supported Apollo Server version.

Choosing an Apollo Server package

Use the right package for your project


⚠️ As of 15 November 2022, Apollo Server 3 is officially deprecated, with end-of-life scheduled for 22 October 2024.

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:

N
Yes
N
Yes
If advanced configuration is required…
N
Yes
Am I running in a serverless environment?
Am I extending an existing HTTP server that
uses a particular Node.js framework?
Use the corresponding
serverless package
Start with apollo-server
Use the corresponding
framework package
Do I want to use a particular
Node.js framework?
Swap to apollo-server-express
Swap to the corresponding
framework package

After you choose a package, see its

.

All supported packages

NameDescription

apollo-server

This "batteries-included" package helps you get started quickly. Recommended for all projects that don't require support or a particular Node.js framework (such as hapi).

Because it sets helpful defaults, this library is also less configurable than other 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 to an

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.

-specific packages

The following libraries are available for running in a particular environment:

  • apollo-server-lambda (AWS Lambda)
  • apollo-server-cloud-functions (Google Cloud Functions)
  • apollo-server-azure-functions (Azure Functions)
  • apollo-server-cloudflare (Cloudflare)

Use each of these libraries if and only if you're running your server in the corresponding service.

Framework-specific packages

The following libraries are available for integrating with a particular Node.js framework:

  • apollo-server-fastify (
    Fastify
    )
  • apollo-server-hapi (
    hapi
    )
  • apollo-server-koa (
    Koa
    )
  • apollo-server-micro (
    Micro
    )

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 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 Promises and async 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:

index.ts
import { ApolloServer } from 'apollo-server';
import { ApolloServerPluginLandingPageLocalDefault } from 'apollo-server-core';
async function startApolloServer(typeDefs, resolvers) {
const server = new ApolloServer({
typeDefs,
resolvers,
csrfPrevention: true,
cache: 'bounded',
plugins: [ApolloServerPluginLandingPageLocalDefault({ embed: true })],
});
const { url } = await server.listen();
console.log(`🚀 Server ready at ${url}`);
}
index.js
import { ApolloServer } from 'apollo-server';
import { ApolloServerPluginLandingPageLocalDefault } from 'apollo-server-core';
async function startApolloServer(typeDefs, resolvers) {
const server = new ApolloServer({
typeDefs,
resolvers,
csrfPrevention: true,
cache: 'bounded',
plugins: [ApolloServerPluginLandingPageLocalDefault({ embed: true })],
});
const { url } = await server.listen();
console.log(`🚀 Server ready at ${url}`);
}

To swap this out for apollo-server-express, we first install the following required packages:

npm 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:

index.ts
import { ApolloServer } from 'apollo-server-express';
import { ApolloServerPluginDrainHttpServer, ApolloServerPluginLandingPageLocalDefault } from 'apollo-server-core';
import express from 'express';
import http from 'http';
async function startApolloServer(typeDefs, resolvers) {
// Required logic for integrating with Express
const app = express();
// Our httpServer handles incoming requests to our Express app.
// Below, we tell Apollo Server to "drain" this httpServer,
// enabling our servers to shut down gracefully.
const httpServer = http.createServer(app);
// Same ApolloServer initialization as before, plus the drain plugin
// for our httpServer.
const server = new ApolloServer({
typeDefs,
resolvers,
csrfPrevention: true,
cache: 'bounded',
plugins: [ApolloServerPluginDrainHttpServer({ httpServer }), ApolloServerPluginLandingPageLocalDefault({ embed: true })],
});
// More required logic for integrating with Express
await server.start();
server.applyMiddleware({
app,
// By default, apollo-server hosts its GraphQL endpoint at the
// server root. However, *other* Apollo Server packages host it at
// /graphql. Optionally provide this to match apollo-server.
path: '/',
});
// Modified server startup
await new Promise<void>((resolve) => httpServer.listen({ port: 4000 }, resolve));
console.log(`🚀 Server ready at http://localhost:4000${server.graphqlPath}`);
}
index.js
import { ApolloServer } from 'apollo-server-express';
import { ApolloServerPluginDrainHttpServer, ApolloServerPluginLandingPageLocalDefault } from 'apollo-server-core';
import express from 'express';
import http from 'http';
async function startApolloServer(typeDefs, resolvers) {
// Required logic for integrating with Express
const app = express();
// Our httpServer handles incoming requests to our Express app.
// Below, we tell Apollo Server to "drain" this httpServer,
// enabling our servers to shut down gracefully.
const httpServer = http.createServer(app);
// Same ApolloServer initialization as before, plus the drain plugin
// for our httpServer.
const server = new ApolloServer({
typeDefs,
resolvers,
csrfPrevention: true,
cache: 'bounded',
plugins: [ApolloServerPluginDrainHttpServer({ httpServer }), ApolloServerPluginLandingPageLocalDefault({ embed: true })],
});
// More required logic for integrating with Express
await server.start();
server.applyMiddleware({
app,
// By default, apollo-server hosts its GraphQL endpoint at the
// server root. However, *other* Apollo Server packages host it at
// /graphql. Optionally provide this to match apollo-server.
path: '/',
});
// Modified server startup
await new Promise((resolve) => httpServer.listen({ port: 4000 }, resolve));
console.log(`🚀 Server ready at http://localhost:4000${server.graphqlPath}`);
}

Package conventions

Each package exports an ApolloServer class. The APIs for these classes are similar but not identical.

All packages depend on apollo-server-core, which contains the code that's shared by all integrations. Certain symbols, such as

, are imported directly from apollo-server-core instead of from a particular package.

All 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 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 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

.

The set of common options supported by each package is listed under

.

Basic usage

The sections below demonstrate how to initialize an ApolloServer instance with each package. More details are available in each package's

.

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

.

apollo-server

apollo-server is the "batteries-included" package. It enables you to spin up a 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.

npm install apollo-server graphql
index.ts
import { ApolloServer } from 'apollo-server';
async function startApolloServer(typeDefs, resolvers) {
const server = new ApolloServer({
typeDefs,
resolvers,
csrfPrevention: true,
cache: 'bounded',
plugins: [ApolloServerPluginLandingPageLocalDefault({ embed: true })],
});
const { url } = await server.listen();
console.log(`🚀 Server ready at ${url}`);
}
index.js
import { ApolloServer } from 'apollo-server';
async function startApolloServer(typeDefs, resolvers) {
const server = new ApolloServer({
typeDefs,
resolvers,
csrfPrevention: true,
cache: 'bounded',
plugins: [ApolloServerPluginLandingPageLocalDefault({ embed: true })],
});
const { url } = await server.listen();
console.log(`🚀 Server ready at ${url}`);
}

Although apollo-server helps you get started quickly, you can't configure its behavior as much as you can other 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

.

apollo-server-express

apollo-server-express is the package for

, the most popular Node.js web framework. It enables you to attach a 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

.

The following example is roughly equivalent to the

above.

npm install apollo-server-express apollo-server-core express graphql
index.ts
import { ApolloServer } from 'apollo-server-express';
import { ApolloServerPluginDrainHttpServer, ApolloServerPluginLandingPageLocalDefault } from 'apollo-server-core';
import express from 'express';
import http from 'http';
async function startApolloServer(typeDefs, resolvers) {
const app = express();
const httpServer = http.createServer(app);
const server = new ApolloServer({
typeDefs,
resolvers,
csrfPrevention: true,
cache: 'bounded',
plugins: [ApolloServerPluginDrainHttpServer({ httpServer }), ApolloServerPluginLandingPageLocalDefault({ embed: true })],
});
await server.start();
server.applyMiddleware({ app });
await new Promise<void>((resolve) => httpServer.listen({ port: 4000 }, resolve));
console.log(`🚀 Server ready at http://localhost:4000${server.graphqlPath}`);
}
index.js
import { ApolloServer } from 'apollo-server-express';
import { ApolloServerPluginDrainHttpServer, ApolloServerPluginLandingPageLocalDefault } from 'apollo-server-core';
import express from 'express';
import http from 'http';
async function startApolloServer(typeDefs, resolvers) {
const app = express();
const httpServer = http.createServer(app);
const server = new ApolloServer({
typeDefs,
resolvers,
csrfPrevention: true,
cache: 'bounded',
plugins: [ApolloServerPluginDrainHttpServer({ httpServer }), ApolloServerPluginLandingPageLocalDefault({ embed: true })],
});
await server.start();
server.applyMiddleware({ app });
await new Promise((resolve) => httpServer.listen({ port: 4000 }, resolve));
console.log(`🚀 Server ready at http://localhost:4000${server.graphqlPath}`);
}

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

:

  • path
  • cors
  • bodyParserConfig
  • onHealthCheck
  • disableHealthCheck

apollo-server-fastify

apollo-server-fastify is the for

, a Node.js web framework. 3 supports Fastify v3.

The following example is roughly equivalent to the

above.

npm install apollo-server-fastify apollo-server-core fastify graphql
index.ts
import { ApolloServer } from 'apollo-server-fastify';
import { ApolloServerPluginDrainHttpServer, ApolloServerPluginLandingPageLocalDefault } from 'apollo-server-core';
import { ApolloServerPlugin } from 'apollo-server-plugin-base';
import fastify, { FastifyInstance } from 'fastify';
function fastifyAppClosePlugin(app: FastifyInstance): ApolloServerPlugin {
return {
async serverWillStart() {
return {
async drainServer() {
await app.close();
},
};
},
};
}
async function startApolloServer(typeDefs, resolvers) {
const app = fastify();
const server = new ApolloServer({
typeDefs,
resolvers,
csrfPrevention: true,
cache: 'bounded',
plugins: [fastifyAppClosePlugin(app), ApolloServerPluginDrainHttpServer({ httpServer: app.server }), ApolloServerPluginLandingPageLocalDefault({ embed: true })],
});
await server.start();
app.register(server.createHandler());
await app.listen(4000);
console.log(`🚀 Server ready at http://localhost:4000${server.graphqlPath}`);
}
index.js
import { ApolloServer } from 'apollo-server-fastify';
import { ApolloServerPluginDrainHttpServer, ApolloServerPluginLandingPageLocalDefault } from 'apollo-server-core';
import fastify from 'fastify';
function fastifyAppClosePlugin(app) {
return {
async serverWillStart() {
return {
async drainServer() {
await app.close();
},
};
},
};
}
async function startApolloServer(typeDefs, resolvers) {
const app = fastify();
const server = new ApolloServer({
typeDefs,
resolvers,
csrfPrevention: true,
cache: 'bounded',
plugins: [fastifyAppClosePlugin(app), ApolloServerPluginDrainHttpServer({ httpServer: app.server }), ApolloServerPluginLandingPageLocalDefault({ embed: true })],
});
await server.start();
app.register(server.createHandler());
await app.listen(4000);
console.log(`🚀 Server ready at http://localhost:4000${server.graphqlPath}`);
}

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

:

  • path
  • cors
  • onHealthCheck
  • disableHealthCheck

See

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 for

, a Node.js web framework. 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

above.

npm install apollo-server-hapi @hapi/hapi graphql
index.ts
import { ApolloServer, ApolloServerPluginStopHapiServer } from 'apollo-server-hapi';
import { ApolloServerPluginLandingPageLocalDefault } from 'apollo-server-core';
import Hapi from '@hapi/hapi';
async function startApolloServer(typeDefs, resolvers) {
const app = Hapi.server({ port: 4000 });
const server = new ApolloServer({
typeDefs,
resolvers,
csrfPrevention: true,
cache: 'bounded',
plugins: [ApolloServerPluginStopHapiServer({ hapiServer: app }), ApolloServerPluginLandingPageLocalDefault({ embed: true })],
});
await server.start();
await server.applyMiddleware({ app });
await app.start();
}
index.js
import { ApolloServer, ApolloServerPluginStopHapiServer } from 'apollo-server-hapi';
import { ApolloServerPluginLandingPageLocalDefault } from 'apollo-server-core';
import Hapi from '@hapi/hapi';
async function startApolloServer(typeDefs, resolvers) {
const app = Hapi.server({ port: 4000 });
const server = new ApolloServer({
typeDefs,
resolvers,
csrfPrevention: true,
cache: 'bounded',
plugins: [ApolloServerPluginStopHapiServer({ hapiServer: app }), ApolloServerPluginLandingPageLocalDefault({ embed: true })],
});
await server.start();
await server.applyMiddleware({ app });
await app.start();
}

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

:

  • path
  • route
  • cors
  • onHealthCheck
  • disableHealthCheck

apollo-server-koa

apollo-server-koa is the for

, a Node.js web framework.

The following example is roughly equivalent to the

above.

npm install apollo-server-koa apollo-server-core koa graphql
index.ts
import { ApolloServer } from 'apollo-server-koa';
import { ApolloServerPluginDrainHttpServer, ApolloServerPluginLandingPageLocalDefault } from 'apollo-server-core';
import Koa from 'koa';
import http from 'http';
async function startApolloServer(typeDefs, resolvers) {
const httpServer = http.createServer();
const server = new ApolloServer({
typeDefs,
resolvers,
csrfPrevention: true,
cache: 'bounded',
plugins: [ApolloServerPluginDrainHttpServer({ httpServer }), ApolloServerPluginLandingPageLocalDefault({ embed: true })],
});
await server.start();
const app = new Koa();
server.applyMiddleware({ app });
httpServer.on('request', app.callback());
await new Promise<void>((resolve) => httpServer.listen({ port: 4000 }, resolve));
console.log(`🚀 Server ready at http://localhost:4000${server.graphqlPath}`);
return { server, app };
}
index.js
import { ApolloServer } from 'apollo-server-koa';
import { ApolloServerPluginDrainHttpServer, ApolloServerPluginLandingPageLocalDefault } from 'apollo-server-core';
import Koa from 'koa';
import http from 'http';
async function startApolloServer(typeDefs, resolvers) {
const httpServer = http.createServer();
const server = new ApolloServer({
typeDefs,
resolvers,
csrfPrevention: true,
cache: 'bounded',
plugins: [ApolloServerPluginDrainHttpServer({ httpServer }), ApolloServerPluginLandingPageLocalDefault({ embed: true })],
});
await server.start();
const app = new Koa();
server.applyMiddleware({ app });
httpServer.on('request', app.callback());
await new Promise((resolve) => httpServer.listen({ port: 4000 }, resolve));
console.log(`🚀 Server ready at http://localhost:4000${server.graphqlPath}`);
return { server, app };
}

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

:

  • path
  • cors
  • bodyParserConfig
  • onHealthCheck
  • disableHealthCheck

apollo-server-micro

apollo-server-micro is the for

, a Node.js web framework.

The following example is roughly equivalent to the

above. You should put this code in a file called index.js in order for the micro CLI to find it.

npm install apollo-server-micro micro graphql
index.ts
import { ApolloServer } from 'apollo-server-micro';
import { ApolloServerPluginLandingPageLocalDefault } from 'apollo-server-core';
const server = new ApolloServer({
typeDefs,
resolvers,
csrfPrevention: true,
cache: 'bounded',
plugins: [ApolloServerPluginLandingPageLocalDefault({ embed: true })],
});
module.exports = server.start().then(() => server.createHandler());
index.js
import { ApolloServer } from 'apollo-server-micro';
import { ApolloServerPluginLandingPageLocalDefault } from 'apollo-server-core';
const server = new ApolloServer({
typeDefs,
resolvers,
csrfPrevention: true,
cache: 'bounded',
plugins: [ApolloServerPluginLandingPageLocalDefault({ embed: true })],
});
module.exports = server.start().then(() => server.createHandler());

Then run the web server with npx micro.

createHandler accepts the following

:

  • 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 for apollo-server-micro. If you use apollo-server-micro, feel free to

!

apollo-server-lambda

apollo-server-lambda is the for

, Amazon's compute service.

This package is a layer around apollo-server-express, which uses the

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

above.

npm install apollo-server-lambda graphql
index.ts
import { ApolloServer } from 'apollo-server-lambda';
import { ApolloServerPluginLandingPageLocalDefault } from 'apollo-server-core';
const server = new ApolloServer({
typeDefs,
resolvers,
csrfPrevention: true,
cache: 'bounded',
plugins: [ApolloServerPluginLandingPageLocalDefault({ embed: true })],
});
exports.handler = server.createHandler();
index.js
import { ApolloServer } from 'apollo-server-lambda';
import { ApolloServerPluginLandingPageLocalDefault } from 'apollo-server-core';
const server = new ApolloServer({
typeDefs,
resolvers,
csrfPrevention: true,
cache: 'bounded',
plugins: [ApolloServerPluginLandingPageLocalDefault({ embed: true })],
});
exports.handler = server.createHandler();

For more details on using apollo-server-lambda, see the

.

apollo-server-cloud-functions

apollo-server-cloud-functions is the for

, Google's compute service.

Because the Cloud Functions Node.js runtime uses Express, apollo-server-cloud-functions is a layer around apollo-server-express.

The following example is roughly equivalent to the

above.

npm install apollo-server-cloud-functions graphql
index.ts
import { ApolloServer } from 'apollo-server-cloud-functions';
import { ApolloServerPluginLandingPageLocalDefault } from 'apollo-server-core';
const server = new ApolloServer({
typeDefs,
resolvers,
csrfPrevention: true,
cache: 'bounded',
plugins: [ApolloServerPluginLandingPageLocalDefault({ embed: true })],
});
exports.handler = server.createHandler();
index.js
import { ApolloServer } from 'apollo-server-cloud-functions';
import { ApolloServerPluginLandingPageLocalDefault } from 'apollo-server-core';
const server = new ApolloServer({
typeDefs,
resolvers,
csrfPrevention: true,
cache: 'bounded',
plugins: [ApolloServerPluginLandingPageLocalDefault({ embed: true })],
});
exports.handler = server.createHandler();

For more details on using apollo-server-cloud-functions, see the

.

apollo-server-azure-functions

apollo-server-azure-functions is the for

, Microsoft's compute service.

The following example is roughly equivalent to the

above.

npm install apollo-server-azure-functions graphql
index.ts
import { ApolloServer } from 'apollo-server-azure-functions';
import { ApolloServerPluginLandingPageLocalDefault } from 'apollo-server-core';
const server = new ApolloServer({
typeDefs,
resolvers,
csrfPrevention: true,
cache: 'bounded',
plugins: [ApolloServerPluginLandingPageLocalDefault({ embed: true })],
});
exports.handler = server.createHandler();
index.js
import { ApolloServer } from 'apollo-server-azure-functions';
import { ApolloServerPluginLandingPageLocalDefault } from 'apollo-server-core';
const server = new ApolloServer({
typeDefs,
resolvers,
csrfPrevention: true,
cache: 'bounded',
plugins: [ApolloServerPluginLandingPageLocalDefault({ embed: true })],
});
exports.handler = server.createHandler();

createHandler accepts the following

:

  • cors
  • onHealthCheck
  • disableHealthCheck

Note that apollo-server-azure-functions does not provide a mechanism for adding arbitrary middleware to your web server (other that by manually wrapping the handler returned by createHandler in your own handler).

For more details on using apollo-server-azure-functions, see the

.

apollo-server-cloudflare

apollo-server-cloudflare is the for

. This package is experimental and is not actively supported by Apollo.

For more details on using with Cloudflare Workers, see the

in the Cloudflare Workers documentation.

Previous
Get started
Next
Migrating to Apollo Server 3
Edit on GitHubEditForumsDiscord

© 2024 Apollo Graph Inc.

Privacy Policy

Company