WebSocket-based subscriptions, pub/sub patterns, and the cursor-based pagination that keeps GraphQL performant at scale.
WebSocket-based subscriptions, pub/sub patterns, and the cursor-based pagination that keeps GraphQL performant at scale.
import { ApolloServer } from '@apollo/server';
import { expressMiddleware } from '@apollo/server/express4';
import jwt from 'jsonwebtoken';
import User from './models/User.js';
const server = new ApolloServer({ typeDefs, resolvers });
await server.start();
app.use('/graphql', expressMiddleware(server, {
context: async ({ req }) => {
const token = req.headers.authorization?.split('Bearer ')[1];
let currentUser = null;
if (token) {
try {
const { id } = jwt.verify(token, process.env.JWT_SECRET);
currentUser = await User.findById(id);
} catch {}
}
return { currentUser };
}
}));
const resolvers = {
Query: {
me: (_, __, { currentUser }) => {
if (!currentUser) throw new Error('Not authenticated');
return currentUser;
},
},
Mutation: {
createPost: (_, { input }, { currentUser }) => {
if (!currentUser) throw new Error('Not authenticated');
if (currentUser.role !== 'author') throw new Error('Not authorized');
return createPost({ ...input, authorId: currentUser.id });
}
}
}requireAuth(context) helper function that throws if currentUser is null. Call it at the top of every protected resolver. Consistent error messages make debugging easier.currentUser = null — don't throw.AuthenticationError → 401. ForbiddenError → 403. Use the right error type.The foundations from today carry directly into Day 5. In the next session the focus shifts to Authentication, Authorization, and Federation — building directly on everything covered here.
Before moving on, verify you can answer these without looking:
Live Bootcamp
Learn this in person — 2 days, 5 cities
Thu–Fri sessions in Denver, Los Angeles, New York, Chicago, and Dallas. $1,490 per seat. June–October 2026.
Reserve Your Seat →