apollo-server, graphql-yoga, and type-graphql are tools that help developers build GraphQL APIs in Node.js, but they serve different roles in the stack. apollo-server is a standalone GraphQL server implementation with extensive plugin support and ecosystem integration. graphql-yoga is a modern, batteries-included GraphQL server that prioritizes developer experience and spec compliance, built on top of Envelop and GraphQL-JS. type-graphql is not a server itself but a library that generates GraphQL schema definitions from TypeScript classes using decorators, often used alongside a GraphQL server like Apollo or Yoga to reduce boilerplate.
When building a GraphQL API in Node.js, you’ll quickly realize these three packages solve different parts of the problem. apollo-server and graphql-yoga are full GraphQL servers — they handle HTTP requests, execute queries, and return responses. type-graphql is a schema-generation tool that works with a server. Understanding their roles is key to making the right architectural choice.
apollo-server is a production-ready GraphQL server that implements the GraphQL specification and provides a robust HTTP layer. It supports middleware, plugins, subscriptions, and integrates tightly with Apollo’s ecosystem.
// apollo-server: Standalone server
import { ApolloServer } from 'apollo-server';
import { typeDefs, resolvers } from './schema';
const server = new ApolloServer({ typeDefs, resolvers });
server.listen().then(({ url }) => console.log(`Running at ${url}`));
graphql-yoga is also a complete GraphQL server, but it’s designed to be simpler and more opinionated. It includes built-in support for GraphQL over HTTP (GET/POST), file uploads, persisted operations, and error masking — all with minimal config.
// graphql-yoga: Zero-config server
import { createYoga } from 'graphql-yoga';
import { createServer } from 'http';
import { schema } from './schema';
const yoga = createYoga({ schema });
const server = createServer(yoga);
server.listen(4000, () => console.log('Running on http://localhost:4000/graphql'));
type-graphql doesn’t run a server. Instead, it lets you define your GraphQL schema using TypeScript classes and decorators. You still need a server (like Apollo or Yoga) to actually serve the API.
// type-graphql: Schema definition only
import { ObjectType, Field, Resolver, Query } from 'type-graphql';
@ObjectType()
class User {
@Field()
id: string;
@Field()
name: string;
}
@Resolver()
class UserResolver {
@Query(() => User)
user() {
return { id: '1', name: 'Alice' };
}
}
// Later, pass the generated schema to a server:
// const schema = await buildSchema({ resolvers: [UserResolver] });
💡 Key insight:
type-graphqlis complementary — you’ll often use it withapollo-serverorgraphql-yoga, not instead of them.
apollo-server traditionally uses SDL-first (Schema Definition Language) — you write .graphql files or template strings, then map resolvers separately.
// apollo-server: SDL + resolver map
const typeDefs = `
type User {
id: ID!
name: String!
}
type Query {
user(id: ID!): User
}
`;
const resolvers = {
Query: {
user: (_, { id }) => getUserById(id)
}
};
graphql-yoga doesn’t enforce a schema style — it accepts any valid GraphQLSchema object. So you can use SDL, code-first libraries like type-graphql, or even graphql-tools.
// graphql-yoga: Works with any schema source
import { schema } from './generated-schema'; // could be from type-graphql, nexus, etc.
const yoga = createYoga({ schema });
type-graphql is purely code-first. It uses decorators to generate both the schema and resolver logic from TypeScript classes, ensuring type safety and reducing duplication.
// type-graphql: Fully code-first
@InputType()
class UserInput {
@Field()
name: string;
}
@Resolver()
class UserResolver {
@Mutation(() => User)
createUser(@Arg('input') input: UserInput) {
return saveUser(input);
}
}
apollo-server offers a rich plugin system (e.g., for caching, tracing, or custom directives) and deep Apollo Studio integration (metrics, schema validation, federated graph management). However, features like file uploads require extra setup (graphql-upload).
// apollo-server: File upload requires extra package
import { GraphQLUpload } from 'graphql-upload';
const typeDefs = `
scalar Upload
type Mutation {
uploadFile(file: Upload!): String
}
`;
graphql-yoga includes file uploads, GraphQL over GET, persisted operations, and error formatting by default. It also supports Envelop plugins for extending behavior without complex middleware.
// graphql-yoga: File uploads work out of the box
const typeDefs = `
scalar File
type Mutation {
uploadFile(file: File!): String
}
`;
// No extra config needed
type-graphql focuses solely on schema generation. It provides validation (via class-validator integration), authorization guards, and dependency injection, but nothing related to HTTP handling or execution context.
// type-graphql: Validation example
import { IsEmail } from 'class-validator';
@InputType()
class RegisterInput {
@Field()
@IsEmail()
email: string;
}
// Validation runs automatically during resolver execution
In practice, many teams combine type-graphql with a server:
type-graphql to generate the schema, then pass it to ApolloServer.import { buildSchema } from 'type-graphql';
import { ApolloServer } from 'apollo-server';
const schema = await buildSchema({ resolvers: [UserResolver] });
const server = new ApolloServer({ schema });
createYoga.import { createYoga } from 'graphql-yoga';
const schema = await buildSchema({ resolvers: [UserResolver] });
const yoga = createYoga({ schema });
This combo gives you type-safe, decorator-based schema definition with the HTTP layer of your choice.
As of 2024, apollo-server v4 is actively maintained, but the Apollo team has shifted focus toward Apollo Server Express and cloud-managed solutions. The core remains stable but sees fewer new features.
graphql-yoga is under active development by The Guild (creators of GraphQL Tools, Envelop, and Hive). It’s positioned as a modern, lightweight alternative with strong emphasis on spec compliance and developer experience.
type-graphql is stable and widely used, though its maintainer has indicated reduced activity. Many developers now consider alternatives like Nexus or GraphQL Code Generator for code-first workflows, but type-graphql remains a solid choice for decorator-based approaches.
| Concern | apollo-server | graphql-yoga | type-graphql |
|---|---|---|---|
| Primary Role | Full GraphQL server | Full GraphQL server | Schema generator (code-first) |
| Best For | Apollo ecosystem, federation | New projects, minimal config | TypeScript, decorator syntax |
| HTTP Layer | Built-in | Built-in | None (requires a server) |
| File Uploads | Requires extra setup | Built-in | N/A |
| Schema Style | SDL-first (by convention) | Any | Code-first only |
| Type Safety | Manual | Manual | Automatic (via decorators) |
apollo-server.graphql-yoga.type-graphql — just remember to pair it with a server like Yoga or Apollo.Don’t think of this as a three-way race. Often, the smartest move is to combine type-graphql with graphql-yoga — you get the best of both worlds: type-safe schema definition and a lean, modern server runtime.
Choose apollo-server if you need deep integration with the Apollo ecosystem (like Apollo Studio, Federation, or Client DevTools), require mature plugin architecture, or are maintaining an existing Apollo-based backend. It’s well-suited for enterprise environments where tooling, observability, and federation are critical, though its configuration can be more verbose compared to newer alternatives.
Choose graphql-yoga if you want a lightweight, modern GraphQL server with zero-config setup, built-in support for GraphQL over HTTP (including persisted operations and file uploads), and seamless integration with frameworks like Next.js or Express. It’s ideal for new projects that prioritize developer ergonomics, spec compliance, and minimal boilerplate without sacrificing flexibility.
Choose type-graphql if you’re using TypeScript and want to define your GraphQL schema and resolvers using class-based decorators, reducing the need to write SDL strings or separate resolver maps. It pairs well with any GraphQL server (like Apollo or Yoga) and is best suited for teams that value strong typing, code-first schema design, and automatic synchronization between TypeScript types and GraphQL schema.

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.
Apollo Server is built with the following principles in mind:
Anyone is welcome to contribute to Apollo Server, just read CONTRIBUTING.md, take a look at the roadmap and make your first PR!
To get started with Apollo Server:
npm install apollo-server-<integration> graphqlThere are two ways to install Apollo Server:
apollo-server package.express, koa, hapi, etc.), use the appropriate Apollo Server integration package.For more info, please refer to the Apollo Server docs.
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
GraphQLSchemaobject fromgraphql-jscan also be specified instead oftypeDefsandresolversusing theschemaproperty: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.
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:
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
};
},
})
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.
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
npm install
npm test
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.Are you stuck? Want to contribute? Come visit us in the Apollo community forum!
Apollo builds open-source software and a graph platform to unify GraphQL across your apps and services. We help you ship faster with:
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.