Event-Based Subscriptions
You now know what a client sees: a stream of reviewAdded results. But where do those results come from? Nothing in the database "sends" anything. On the server, subscriptions are wired to events: something announces that a review was added, and every interested subscriber gets a result.
The rule
Publish the event, filter by arguments, run the selection, push.
Most GraphQL setups use a small publish/subscribe (pub/sub) helper. The mutation that adds a review publishes an event; the subscription field listens for it:
const resolvers = {
Mutation: {
addReview: async (_, { input }, { db, pubsub }) => {
const review = await db.insertReview(input);
pubsub.publish("REVIEW_ADDED", review);
return review;
},
},
Subscription: {
reviewAdded: {
subscribe: (_, { bookId }, { pubsub }) =>
onlyWhere(pubsub.subscribe("REVIEW_ADDED"),
(review) => review.bookId === bookId),
resolve: (review) => review,
},
},
};Library names differ (onlyWhere here stands for whatever filter helper yours offers), but the four steps are always the same:
- Publish: some code, usually a mutation resolver, announces an event with a payload, here the new review.
- Filter: each subscription's
subscribefunction turns the event stream into only the events it cares about, using the subscription's arguments (bookId). - Run the selection: for each event that passes, the server executes the client's selection set with the payload as the root value. Nested fields such as
book { title }run their normal resolvers, once per event. - Push: the finished result goes down that client's open connection.
The event is the trigger, not the answer. A payload can be small (just an ID) as long as resolvers can fetch the rest.
One practical catch: a simple pub/sub lives in one server's memory. If the bookshop runs two server instances and the mutation lands on instance A while the subscriber is connected to instance B, B never hears it. Production setups send events through a shared message broker that every instance listens to.
The shortcut
To debug "my subscriber got nothing", walk the four steps in order and find where the event stopped.
Publish
Did
addReviewcallpublish("REVIEW_ADDED", ...)? Yes, the log shows it.
Drills
Answer fast — trust the rule.
In the bookshop, what causes a reviewAdded result to be sent?
A client subscribed with bookId: "b1". A review is added to b2. What does this client receive?
A subscriber selects rating book { title }. When does the Book.title resolver run?
The mutation runs on server instance A; the subscriber is connected to instance B. With in-memory pub/sub, what happens?
Remember
- Publish the event, filter by arguments, run the selection, push.
- Debug by walking those four steps until you find where the event stopped.
- Trap: in-memory pub/sub does not cross server instances.
