Handle unsubscribe GraphQL subscription

I have an issue with subscription can’t be unsubscribe.

Before we start, this is my setup: Apollo Client(graphql-ws) <-> Apollo Server(graphql-ws). On the server, I build a custom PubSub instead of using the one provided.

As you can see here, the client has sent a complete request to server with the id. However, the server is still sending more data to it. I have read somewhere that you have to send GQL_STOP, aka STOP instead. However, this is what Apollo Client is sending.

A bit of code:

Client subscription:

export const useGetDataThroughSubscription = (
	resourceIds: number[],
	startDate?: Date,
	endDate?: Date
) => {
	const variables = {
		startTime: startDate?.toISOString() ?? '',
		endTime: endDate?.toISOString() ?? '',

	return useGetDataSubscription({

Server pubsub:

const createPubSub = <TopicPayload extends { [key: string]: unknown }>(
	emitter: EventEmitter = new EventEmitter()
) => ({
	publish: <Topic extends Extract<keyof TopicPayload, string>>(
		topic: Topic,
		payload: TopicPayload[Topic]
	) => {
		emitter.emit(topic as string, payload);
	async *subscribe<Topic extends Extract<keyof TopicPayload, string>>(
		topic: Topic,
		retrievalFunc: (value: TopicPayload[Topic]) => Promise<any>
	): AsyncIterableIterator<TopicPayload[Topic]> {
		const asyncIterator = on(emitter, topic);
		for await (const [value] of asyncIterator) {
			const data = await retrievalFunc(value);
			yield data;

Server subscribe to event:

const resolver: Resolvers = {
	Subscription: {
		[onGetAllLocationsEvent]: {
			async *subscribe(_a, _b, ctx) {
				const locations = await ...;

				yield locations;

				const iterator = ctx.pubsub.subscribe(
					async (id: number) => {
						const location = ...;

						return location;

				for await (const data of iterator) {
					if (data) {
						yield [data];
			resolve: (payload) => payload,

In this one, if instead of the for loop, I return iterator instead, then the server will send back a complete and stop the subscription all together. That’s great, but I want to keep the connection open until client stop listening.

And server publish

ctx.pubsub.publish(onGetAllResourcesEvent, resource.id);

So how should I deal with this?