GraphQL Yoga
GraphQL Yoga: a fast, low-config Node server with great defaults. Schema, resolvers, plugins, file uploads, subscriptions.
GraphQL — Yoga
EXAMPLE
# ===== Why Yoga =====
# - Tiny core, plugin-driven
# - Built on graphql.js + envelop
# - Multipart uploads, SSE / WebSocket subscriptions
# - Plays well with Codegen + Apollo clients
# ===== Install =====
npm install graphql-yoga graphql
# ===== Smallest server =====
# server.mjs
import { createYoga, createSchema } from 'graphql-yoga';
import { createServer } from 'node:http';
const yoga = createYoga({
schema: createSchema({
typeDefs: \`
type Query { hello: String! }
type Mutation { say(msg: String!): String! }
\`,
resolvers: {
Query: { hello: () => 'world' },
Mutation: { say: (_, { msg }) => 'echo: ' + msg },
},
}),
});
createServer(yoga).listen(4000, () => console.log('http://localhost:4000/graphql'));
# Visit http://localhost:4000/graphql -> GraphiQL playground.
# ===== Context =====
import { createYoga, createSchema } from 'graphql-yoga';
const yoga = createYoga({
schema,
context: ({ request }) => ({
user: getUserFromAuth(request.headers.get('authorization')),
db,
}),
});
# In resolvers: (_, args, context) => context.user
# ===== Subscriptions (SSE-first; WebSocket optional) =====
const yoga = createYoga({
schema: createSchema({
typeDefs: \`
type Subscription { ticks: Int! }
type Query { _ : Int }
\`,
resolvers: {
Subscription: {
ticks: {
subscribe: async function* () {
for (let i = 0; ; i++) {
yield { ticks: i };
await new Promise(r => setTimeout(r, 1000));
}
},
},
},
},
}),
});
# Client:
const es = new EventSource('http://localhost:4000/graphql?query=subscription{ticks}');
es.addEventListener('next', e => console.log(JSON.parse(e.data)));
# ===== File uploads =====
# Yoga supports graphql-multipart-request-spec out of the box.
import { useGraphQLMultipart } from '@graphql-yoga/plugin-graphql-multipart';
const yoga = createYoga({
schema,
plugins: [useGraphQLMultipart()],
});
# typeDefs:
# scalar File
# type Mutation { upload(file: File!): String! }
# resolver:
# upload: async (_, { file }) => {
# const stream = file.createReadStream(); ...
# }
# ===== Plugins (envelop) =====
import { useResponseCache } from '@graphql-yoga/plugin-response-cache';
import { useGraphQLArmor } from '@escape.tech/graphql-armor';
const yoga = createYoga({
schema,
plugins: [
useResponseCache({ session: () => null }),
useGraphQLArmor(), // depth + complexity + cost limits
],
});
# ===== Auth =====
# Use envelop plugins like useGenericAuth or your own context wrapper.
# Throw GraphQLError with extensions code for typed client handling.
# ===== Persisted queries =====
import { usePersistedOperations } from '@graphql-yoga/plugin-persisted-operations';
const yoga = createYoga({
schema,
plugins: [
usePersistedOperations({
getPersistedOperation(key) { return store[key]; },
}),
],
});
# ===== Patterns to internalise =====
# - createSchema + createYoga = full server in 20 lines
# - Context for auth + datasources
# - Armor + persisted operations on public APIs
# - SSE for subscriptions unless you specifically need WS
# ===== Pitfalls =====
# - No depth / complexity limit on public APIs -> DoS risk (add Armor)
# - Mixing Yoga + Apollo Server resolver shapes inconsistently
# - Forgetting to type custom directives -> runtime errors
# - Heavy persisted op store with no eviction -> memory grows
Why it matters
Yoga is a quick, low-config GraphQL server with strong defaults. createSchema + createYoga + a context function is most apps. Layer plugins for caching, security (Armor), persisted operations. Reach for it when Apollo Server feels heavy and you want a Node-native, plugin-driven server.
Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.
Example
Example
import { createYoga, createSchema } from 'graphql-yoga';
import { createServer } from 'node:http';
const yoga = createYoga({ schema: createSchema({ typeDefs, resolvers }) });
createServer(yoga).listen(4000);
Try it Yourself »
Discussion
Loading…