Does Apollo client perform any garbage collection on watches?

I am working on a large app and have noticed performance degrade over time.

From inspecting the cache I can see over 20,000 watches in the cache:
InMemoryCache2 {watches: Set(21126), typenameDocumentCache: Map(286), txCount: 0, getFragmentDoc: ƒ, makeVar: ƒ, …}

The watches don’t appear to get garbage collected when the component that called useQuery is unmounted so the watches Set just increases in size over time.

Is this expected behaviour?

And is there way to remove watches on unmount, or trigger a garbage collect somehow?

Thanks

Hi @John_Davison :wave: thanks for posting! What version of @apollo/client are you using?

Hi @JeffAuriemma thanks for the quick response. We’re on "@apollo/client": "3.7.14"

Thanks! @John_Davison can you confirm this is a web application running in the browser and not a React Native app?

Hi @JeffAuriemma yes this is an web app running in the browser.

I’ve been investigating further and found that the main culprit is a hook that we use to make several useQuery calls (relying on cache hits to avoid network requests after the first one).

This hook gets called from several places within a very busy part of our app which means the useQuery hooks are called many times in quick succession.

From what I’ve observed, when this happens in quick succession, not all the watches are unregistered on unmount, which leads to a gradual increase in watches that will never be removed.

Looking at the useQuery hook code, the unsubscribe part looks pretty straight forward so I’m not sure why this is happening.

For now, I’ve mitigated this somewhat by switching from useQuery to client.query for queries that don’t need to be observed.

And where queries do need to be observed I’ve moved the useQuery call up to a context.

This seems to be working for us for now, but it would be great if you are able to look into this.

Many thanks
John

Thanks @John_Davison!

Can I ask for a few more details about this? Are you getting 100% cache hits on the subsequent useQuery calls?

Hi @JeffAuriemma yes we are getting 100% cache hits for subsequent useQuery calls

I have an update for you @John_Davison - we’re not sure what might be going on under the hood here with the information given but we are interested in getting a more robust picture of general scalability challenges associated with useQuery. We’ll be taking a deeper look at this in the foreseeable future and will be sharing our findings in the apollo-client repo. Glad you found a workaround for the time being, stay tuned!