apollo-server vs express-graphql
Building GraphQL APIs in Node.js
apollo-serverexpress-graphqlSimilar Packages:

Building GraphQL APIs in Node.js

apollo-server and express-graphql are both tools for running GraphQL servers on Node.js. express-graphql is a middleware for Express that handles GraphQL requests directly within an Express app. apollo-server is a complete server solution that includes schema definition, resolvers, and built-in features like caching and tracing. While both solve the same core problem, they differ significantly in maintenance status and feature depth.

Npm Package Weekly Downloads Trend

3 Years

Github Stars Ranking

Stat Detail

Package
Downloads
Stars
Size
Issues
Publish
License
apollo-server013,95426.6 kB883 years agoMIT
express-graphql06,255-546 years agoMIT

Apollo Server vs Express-GraphQL: Architecture, Maintenance, and Features

Both apollo-server and express-graphql allow you to serve GraphQL APIs using Node.js, but they take different approaches to integration and lifecycle management. express-graphql acts as middleware for an existing Express app, while apollo-server provides a standalone server experience that can also integrate with Express. Let's compare how they handle common server tasks.

โš ๏ธ Maintenance Status: Active vs Deprecated

apollo-server is actively maintained by the Apollo GraphQL team.

  • Receives regular security updates and feature additions.
  • Supports the latest GraphQL specifications and Apollo Federation.
// apollo-server: Active development
import { ApolloServer } from 'apollo-server';
const server = new ApolloServer({ typeDefs, resolvers });

express-graphql is officially deprecated.

  • No new features or security patches are being released.
  • The GraphQL foundation recommends moving to other solutions.
// express-graphql: Deprecated
import { graphqlHTTP } from 'express-graphql';
app.use('/graphql', graphqlHTTP({ schema }));

๐Ÿš€ Setup & Integration: Standalone vs Middleware

apollo-server runs as a standalone HTTP server by default.

  • You define the schema and resolvers, then call listen().
  • It handles HTTP parsing, CORS, and body parsing automatically.
// apollo-server: Standalone setup
const server = new ApolloServer({ typeDefs, resolvers });
const { url } = await server.listen({ port: 4000 });
console.log(`Server ready at ${url}`);

express-graphql requires an existing Express application.

  • You attach it to a specific route using app.use().
  • You must manage Express middleware stack order yourself.
// express-graphql: Express middleware
const app = express();
app.use('/graphql', graphqlHTTP({
  schema,
  graphiql: true
}));
app.listen(3000);

๐Ÿ“ Schema Definition: SDL vs Programmatic

apollo-server prefers Schema Definition Language (SDL).

  • You write types in a string format similar to IDL.
  • Resolvers are passed separately as a map.
// apollo-server: SDL
const typeDefs = `
  type Query {
    hello: String
  }
`;
const resolvers = {
  Query: { hello: () => 'world' }
};

express-graphql accepts a GraphQL Schema object.

  • You often build the schema using buildSchema or makeExecutableSchema.
  • Less emphasis on separating type definitions from logic.
// express-graphql: Schema Object
const schema = buildSchema(`
  type Query {
    hello: String
  }
`);
const root = { hello: () => 'world' };

๐Ÿ”„ Context & Request Handling

apollo-server provides a structured context object.

  • The context function runs for every request.
  • You can inject auth tokens, loaders, or database connections easily.
// apollo-server: Context function
const server = new ApolloServer({
  typeDefs,
  resolvers,
  context: ({ req }) => ({
    user: getUserFromToken(req.headers.authorization)
  })
});

express-graphql passes context via the middleware config.

  • You can pass a function or a static object.
  • Access to the raw Express request and response is direct.
// express-graphql: Context via middleware
app.use('/graphql', graphqlHTTP((req, res) => ({
  schema,
  context: { req, res }
})));

๐Ÿงฉ Plugins & Extensions

apollo-server has a rich plugin system.

  • Built-in support for tracing, caching, and metrics.
  • You can write custom plugins to hook into lifecycle events.
// apollo-server: Plugin usage
const server = new ApolloServer({
  typeDefs,
  resolvers,
  plugins: [
    { async requestDidStart() { console.log('Request started'); } }
  ]
});

express-graphql has minimal extension support.

  • Relies on Express middleware for logging or auth.
  • No built-in tracing or performance monitoring features.
// express-graphql: External middleware
app.use('/graphql', graphqlHTTP({ schema }));
// Logging handled by separate Express middleware like morgan

๐Ÿค Similarities: Shared Ground

While the differences are clear, both packages share some core concepts.

1. ๐Ÿ“š Both Use GraphQL.js

  • Both rely on the reference graphql implementation.
  • Support standard queries, mutations, and subscriptions.
// Shared: GraphQL execution
// Both packages ultimately call graphql() from the 'graphql' package

2. ๐Ÿ›ก๏ธ Basic Security Features

  • Both allow disabling introspection in production.
  • Both support setting CORS headers.
// apollo-server: Introspection
new ApolloServer({ ..., introspection: false });

// express-graphql: Introspection
graphqlHTTP({ schema, graphiql: false });

3. ๐Ÿงช Testing Support

  • Both can be tested without a running HTTP server.
  • You can execute queries directly against the schema.
// Shared: Direct execution
const result = await graphql({ schema, source: query });

๐Ÿ“Š Summary: Key Differences

Featureapollo-serverexpress-graphql
Statusโœ… Active MaintenanceโŒ Deprecated
Integrationโ˜๏ธ Standalone or Express๐Ÿงฉ Express Middleware Only
Schema๐Ÿ“ SDL Strings๐Ÿ“„ Schema Objects
Plugins๐Ÿงฉ Rich Plugin Systemโž– Minimal
Tracing๐Ÿ“ˆ Built-in Supportโž– Manual Implementation
Subscriptionsโœ… Built-in Supportโš ๏ธ Complex Setup

๐Ÿ’ก The Big Picture

apollo-server is like a complete vehicle ๐Ÿš— โ€” it comes with an engine, wheels, and dashboard ready to go. It is ideal for teams building production APIs who need monitoring, federation, and long-term support.

express-graphql is like a wheel kit ๐Ÿ›ž โ€” it adds GraphQL capability to an existing Express app but lacks the surrounding infrastructure. It was useful for simple prototypes but is now unsafe for new development due to deprecation.

Final Thought: For any new project, apollo-server is the only safe choice. If you are using express-graphql, plan a migration path to apollo-server or @apollo/server to ensure security and feature compatibility.

How to Choose: apollo-server vs express-graphql

  • apollo-server:

    Choose apollo-server for new projects requiring long-term support, advanced features like federation, and active maintenance. It offers a robust plugin system and better integration with modern Apollo tools. This package is the standard choice for production GraphQL APIs today.

  • express-graphql:

    Do not choose express-graphql for new projects as it is officially deprecated. Only consider this if maintaining a legacy system where migrating would cause significant disruption without immediate benefit. You should plan to move to a supported alternative like apollo-server or graphql-http.

README for apollo-server

Apollo Server

A TypeScript GraphQL Server for Express, Koa, Hapi, Lambda, and more.

npm version Build Status Join the community forum Read CHANGELOG

Apollo Server is a community-maintained open-source GraphQL server. It works with many Node.js HTTP server frameworks, or can run on its own with a built-in Express server. Apollo Server works with any GraphQL schema built with GraphQL.js--or define a schema's type definitions using schema definition language (SDL).

Read the documentation for information on getting started and many other use cases and follow the CHANGELOG for updates.

Principles

Apollo Server is built with the following principles in mind:

  • By the community, for the community: Its development is driven by the needs of developers.
  • Simplicity: By keeping things simple, it is more secure and easier to implement and contribute.
  • Performance: It is well-tested and production-ready.

Anyone is welcome to contribute to Apollo Server, just read CONTRIBUTING.md, take a look at the roadmap and make your first PR!

Getting started

To get started with Apollo Server:

  • Install with npm install apollo-server-<integration> graphql
  • Write a GraphQL schema
  • Use one of the following snippets

There are two ways to install Apollo Server:

  • Standalone: For applications that do not require an existing web framework, use the apollo-server package.
  • Integrations: For applications with a web framework (e.g. express, koa, hapi, etc.), use the appropriate Apollo Server integration package.

For more info, please refer to the Apollo Server docs.

Installation: Standalone

In a new project, install the apollo-server and graphql dependencies using:

npm install apollo-server graphql

Then, create an index.js which defines the schema and its functionality (i.e. resolvers):

const { ApolloServer, gql } = require('apollo-server');

// The GraphQL schema
const typeDefs = gql`
  type Query {
    "A simple type for getting started!"
    hello: String
  }
`;

// A map of functions which return data for the schema.
const resolvers = {
  Query: {
    hello: () => 'world',
  },
};

const server = new ApolloServer({
  typeDefs,
  resolvers,
});

server.listen().then(({ url }) => {
  console.log(`๐Ÿš€ Server ready at ${url}`);
});

Due to its human-readability, we recommend using schema-definition language (SDL) to define a GraphQL schema--a GraphQLSchema object from graphql-js can also be specified instead of typeDefs and resolvers using the schema property:

const server = new ApolloServer({
  schema: ...
});

Finally, start the server using node index.js and go to the URL returned on the console.

For more details, check out the Apollo Server Getting Started guide and the fullstack tutorial.

For questions, the Apollo community forum is a great place to get help.

Installation: Integrations

While the standalone installation above can be used without making a decision about which web framework to use, the Apollo Server integration packages are paired with specific web frameworks (e.g. Express, Koa, hapi).

The following web frameworks have Apollo Server integrations, and each of these linked integrations has its own installation instructions and examples on its package README.md:

Context

A request context is available for each request. When context is defined as a function, it will be called on each request and will receive an object containing a req property, which represents the request itself.

By returning an object from the context function, it will be available as the third positional parameter of the resolvers:

new ApolloServer({
  typeDefs,
  resolvers: {
    Query: {
      books: (parent, args, context, info) => {
        console.log(context.myProperty); // Will be `true`!
        return books;
      },
    }
  },
  context: async ({ req }) => {
    return {
      myProperty: true
    };
  },
})

Documentation

The Apollo Server documentation contains additional details on how to get started with GraphQL and Apollo Server.

The raw Markdown source of the documentation is available within the docs/ directory of this monorepo--to contribute, please use the Edit on GitHub buttons at the bottom of each page.

Development

If you wish to develop or contribute to Apollo Server, we suggest the following:

  • Fork this repository

  • Install Direnv (a tool that automatically sets up environment variables in project directories) or nvm. We use nvm to ensure we're running the expected version of Node (and we use Direnv to install and run nvm automatically).

  • Install the Apollo Server project on your computer

git clone https://github.com/[your-user]/apollo-server
cd apollo-server
direnv allow  # sets up nvm for you; if you installed nvm yourself, try `nvm install` instead
  • Build and test
npm install
npm test
  • To run individual test files, run npm run pretest && npx jest packages/apollo-server-foo/src/__tests__/bar.test.ts. Note that you do need to re-compile TypeScript before each time you run a test, or changes across packages may not be picked up. Instead of running npm run pretest from scratch before each test run, you can also run tsc --build tsconfig.json --watch in another shell, or use the VSCode Run Build Task to run that for you.

Community

Are you stuck? Want to contribute? Come visit us in the Apollo community forum!

Maintainers

Who is Apollo?

Apollo builds open-source software and a graph platform to unify GraphQL across your apps and services. We help you ship faster with:

  • Apollo Studio โ€“ A free, end-to-end platform for managing your GraphQL lifecycle. Track your GraphQL schemas in a hosted registry to create a source of truth for everything in your graph. Studio provides an IDE (Apollo Explorer) so you can explore data, collaborate on queries, observe usage, and safely make schema changes.
  • Apollo Federation โ€“ The industry-standard open architecture for building a distributed graph. Use Apolloโ€™s gateway to compose a unified graph from multiple subgraphs, determine a query plan, and route requests across your services.
  • Apollo Client โ€“ The most popular GraphQL client for the web. Apollo also builds and maintains Apollo iOS and Apollo Android.
  • Apollo Server โ€“ A production-ready JavaScript GraphQL server that connects to any microservice, API, or database. Compatible with all popular JavaScript frameworks and deployable in serverless environments.

Learn how to build with Apollo

Check out the Odyssey learning platform, the perfect place to start your GraphQL journey with videos and interactive code challenges. Join the Apollo Community to interact with and get technical help from the GraphQL community.