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

pnpm add graphql-yoga graphql
Make a schema, create Yoga and start a Node server:
import { createServer } from 'node:http'
import { createSchema, createYoga } from 'graphql-yoga'
const yoga = createYoga({
schema: createSchema({
typeDefs: /* GraphQL */ `
type Query {
hello: String
}
`,
resolvers: {
Query: {
hello: () => 'Hello from Yoga!'
}
}
})
})
const server = createServer(yoga)
server.listen(4000, () => {
console.info('Server is running on http://localhost:4000/graphql')
})
envelop plugins.Our documentation website will help you get started.
We've made sure developers can quickly start with GraphQL Yoga by providing a comprehensive set of
examples.
See all of them in the examples/ folder.
Read more about how GraphQL Yoga compares to other servers in the ecosystem here.
If this is your first time contributing to this project, please do read our Contributor Workflow Guide before you get started off.
For this project in particular, to get started on stage/2-failing-test:
npm i -g pnpm@8 && pnpm install && pnpm buildpackages/graphql-yoga/__tests__ using Jest APIspnpm testFeel free to open issues and pull requests. We're always welcome support from the community.
Help us keep Yoga open and inclusive. Please read and follow our Code of Conduct as adopted from Contributor Covenant.
MIT