Jared Brown
Jared Brown5mo ago

Client side caching / costs?

Hello! Looking at Convex, I noticed that it is recommended to have a useQuery for pretty much every data read—which makes sense, at least for initial application render. But is there any client side caching to prevent repetitive function calls for data that isn't updating? Thinking of apps where you may call several queries per page, but the underlying data isn't changing regularly (profile photos, names, titles of documents, etc)—so it seems like you're unnecessarily going to rack up a large amount of function calls. Curious if this is something to think about, or not? Obviously free tier gets you very far, but just curious from an architecture/data fetching standpoint what the "best" E2E strategy is for both BE/FE performance and usage stats.
7 Replies
jamwt
jamwt5mo ago
Convex
YouTube
Can your database do this? Ep. 1: Magic caching
A Next.js app with no query cache? Jank. One with a cache? No more jank, but now we need to deal with cache invalidation and application consistency. Ugh. But with Convex's magic query cache, Convex's powerful subscriptions are cached, not merely values. So you get the best of both words. Repository here: https://github.com/jamwt/cached-dmv ...
jamwt
jamwt5mo ago
or, using tanstack-query (react-query) works https://docs.convex.dev/client/tanstack-query
Convex with TanStack Query | Convex Developer Hub
If you already use TanStack Query the query
jamwt
jamwt5mo ago
also, by default, if you use the same query N times on a page, the convex react library collapses them into only subscription these other approaches go further and keep the subscription cache alive on unmount/remount cycles if someone is navigating around your app
Jared Brown
Jared BrownOP5mo ago
nice! this is sick—thank you! How many function calls would this result in? For example, if you had the viewer cached on the clientside / subsequently had subscribed to it Just the one, or each read/update? 🤔 tried to test some things and checking dashboard, unclear (not deal breakers or complaints, just genuinely curious how it works) Also wondering why it isn’t the default behavior of the client? From the example / video, it looks like how you’d always want this to function - so what’s the tradeoff you’re making when using the cache provider and query?
jamwt
jamwt5mo ago
1. more complexity. I don't want to trivialize that too much, understanding what's happening can be a little more difficult so we normally like folks to opt-in to that 2. it's possible this will either save or cost you money depending on the usage pattern of your app if you have a lot of background mutations on data with a lot of subscribers, then you'll have "unseen" subscriptions pulling updates (and costing function calls) if you have a low amount of mutations on data with a lot of subscribers, you'll end up saving money by not-reinvoking a function when folks "nav back" to previous views so it's not clear-cut what's a win. ergo we keep it simple until folks can internalize these tradeoffs and choose a mutation with a single subscriber costs two function calls -- one for the mutation and one for the automatic query re-run for any active subscriptions so with single player data you could imagine the session being like 1, 3, 5, 7, 9 function calls as they load the page and then make changes
Jared Brown
Jared BrownOP5mo ago
This is an insanely helpful answer, makes a lot of sense - thank you so much! Have a mix of low mutation , vs highly mutated data via workflows - so a super clear separation there on which to use and why. Really appreciate the thoughtful breakdown 🙏

Did you find this page helpful?