graphql-tools and Apollo GraphQL aren’t really competing products; they’re more like building blocks where Apollo GraphQL uses graphql-tools under the hood.
Let’s see graphql-tools in action, building a simple schema from scratch. Imagine you have a few types defined in your GraphQL schema language (SDL):
type Book {
title: String!
author: String!
year: Int
}
type Query {
books: [Book!]!
bookByTitle(title: String!): Book
}
With graphql-tools, you can take this SDL and add "resolvers" – the functions that actually fetch the data for each field.
import { makeExecutableSchema } from 'graphql-tools';
const typeDefs = `
type Book {
title: String!
author: String!
year: Int
}
type Query {
books: [Book!]!
bookByTitle(title: String!): Book
}
`;
const booksData = [
{ title: "The Hitchhiker's Guide to the Galaxy", author: "Douglas Adams", year: 1979 },
{ title: "Pride and Prejudice", author: "Jane Austen", year: 1813 },
{ title: "1984", author: "George Orwell", year: 1949 },
];
const resolvers = {
Query: {
books: () => booksData,
bookByTitle: (_, { title }) => booksData.find(book => book.title === title),
},
};
const schema = makeExecutableSchema({ typeDefs, resolvers });
export default schema;
This schema object is now a fully functional GraphQL schema that can be served by a GraphQL server. graphql-tools provides the core functionality to stitch together your schema definition and your data-fetching logic.
Apollo GraphQL, on the other hand, is a comprehensive platform for building and managing GraphQL APIs. Think of it as a set of tools that uses graphql-tools (and the underlying graphql-js library) but adds much more.
Here’s what Apollo brings to the table:
- Server:
apollo-serveris a popular, batteries-included GraphQL server that works with various Node.js frameworks (Express, Koa, Hapi, etc.) or as a standalone server. It simplifies setting up an endpoint. - Client:
apollo-clientis a powerful GraphQL client for the frontend (React, Vue, Angular, etc.) that manages caching, state management, and network requests. - Gateway:
apollo-gatewayallows you to build a single GraphQL API from multiple microservices (a "supergraph"). - DevTools: Apollo Studio provides a hosted platform for managing your GraphQL schema, monitoring performance, and exploring your API.
When you use apollo-server, you’re often still defining your typeDefs and resolvers much like in the graphql-tools example. Apollo Server then takes these and uses graphql-tools internally to create the executable schema.
import { ApolloServer } from 'apollo-server';
import { makeExecutableSchema } from 'graphql-tools'; // Apollo Server uses this!
// ... (typeDefs and resolvers from the previous example) ...
const schema = makeExecutableSchema({ typeDefs, resolvers });
const server = new ApolloServer({ schema });
server.listen().then(({ url }) => {
console.log(`🚀 Server ready at ${url}`);
});
The core difference is the scope: graphql-tools is a library for schema construction, while Apollo GraphQL is a full-stack ecosystem for GraphQL development. You can use graphql-tools on its own to build your schema and then integrate it with any GraphQL server. However, Apollo provides a more opinionated and integrated experience, especially if you’re building a complex application or want features like managed caching and a unified API gateway.
The one thing most people miss is that graphql-tools itself is quite low-level. It gives you the power to define your schema and resolvers, but it doesn’t prescribe how you should serve it, how you should handle authentication, or how you should manage client-side state. Apollo, by providing apollo-server and apollo-client, offers these higher-level abstractions and integrations, making it easier to get a full GraphQL application up and running quickly.
The next step after understanding this distinction is often exploring how to integrate Apollo Client with a frontend framework to consume the Apollo Server API.