Clever Tagline
Clever Tagline4mo ago

Something's still not clicking. Can you

Something's still not clicking. Can you give some examples where caching would be a detriment due to the problems you listed?
13 Replies
Hmza
Hmza4mo ago
Sure! Let's say you're building a food delivery app with Convex, and caching is enabled by default. If you update the prices of menu items in the backend, users could still see outdated (cached) prices when browsing, because the cache isn't instantly refreshed. This means they’d see the stale pricing until the cache expires or they manually refresh the page. By not enabling query caching by default, Convex ensures that users always get real-time data, like updated prices, without having to worry about stale information causing issues. This is crucial for dynamic data, where things like stock, pricing, or order availability need to be updated instantly.
Clever Tagline
Clever TaglineOP4mo ago
@Hmza That makes sense, but I keep thinking back to the caching example that was shown in this video: https://www.youtube.com/watch?v=ZgxDlSUGpfE&t=307s In that demo, the data was updating (via a cron) and the caches appeared to refresh at each update.
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 ...
Clever Tagline
Clever TaglineOP4mo ago
That's one of the things that prompted me to add caching to my app in the first place: seeing that data updates appeared to force-refresh the cache so that what the app displays is never stale. In traditional caching, I can see how the example you shared might lead to stale data, but the way query caching is implemented in Convex (via the helpers) appears to circumvent that problem.
Hmza
Hmza4mo ago
You're absolutely right, and I apologize for the confusion in my previous explanation.you've touched on a key feature of convex that sets it apart from traditional caching systems. convex has a reactive caching system and is indeed designed to automatically update when the underlying data changes, as demonstrated in that video. by Jamie. This means that even with caching enabled, you'll always see the most up-to-date data without manual refreshes or waiting for cache expiration. The query caching helper in Convex is primarily used for performance optimization rather than preventing stale data. this allow you to fine-tune which queries should be cached and how, which can be especially useful for complex queries or in scenarios where you want to balance between real-time updates and reducing database load. so in my example of food delivery app the updated prices will immediately reflect even with cache query. Helper just gives you extra control to this behaviour. thank you for bringing this up
Hmza
Hmza4mo ago
reference to this : https://stack.convex.dev/platform-you-need you can read how "Caching" is explained and how it works in convex
The platform you need, when you need it
You don’t have to worry about the platform locking you into a decision that seems convenient at first but is a headache to deal with later.
Clever Tagline
Clever TaglineOP4mo ago
Thanks for that! I wasn't aware that Convex cached on the backend. Again, just one more reason to love it!
erquhart
erquhart4mo ago
Jamie's helper is one of a number of things they've built outside of the core intentionally. They want to keep the core lean and only graduate things into the core once they're confident in the approach, ergonomics, etc. This helper specifically is a good example of a high impact/low effort pattern that is enabled by Convex as a system, so Jamie put it together for the video and the team made improvements. They're a small team, so this approach has the added benefit of not increasing their guaranteed support scope. Although they've continued to support helpers and other non-core libs about as well as anything else.
djbalin
djbalin4mo ago
@erquhart Can you help me understand this as well please 🙂 The caching feature from the helper library doesn't affect how the backend caching behaves, does it? As far as I understand, the helper simply keeps a query connection (i.e. useQuery) between client and Convex alive for some time (default 5 min) after a React component containing a useQuery unmounts. The potential benefit is then that, if we re-mount that same React component within the keep-alive time, we don't have to re-establish connection to the server, since it's still alive?
erquhart
erquhart4mo ago
Yeah the helper is entirely client side. The point of difference is deciding what goes in the core and what is left to be implemented in user land. The team's goal as I understand it is that once something is in core, it can generally be expected to stay there. So they'll start a pattern in userland to get some mileage, then they can make a decision based on experience whether and how to incorporate it into the core libs. There will always be a layer of very useful things that are left to be implemented outside of the main libs.
ballingt
ballingt4mo ago
Using "caching" to describe the behavior of Jamie's addon is interesting, it's accurate but maybe confusing. The most important kind of caching in Convex is that a query doesn't have to re-run if re-requested when none of the underlying data has changed. That's the "magic" perfect server-side caching. A useful thing for clients to do is to "subscribe" to queries, so that every time the query result for a subscribed query changes on the backend, they recieve an update. In React this is the useQuery() hook, which causes a component to rerender whenever the result of the query changes. Another useful thing for client to do, that they don't do by default with the Convex React library, is remember that a query was subscribed to in a component and say subscribed to it even after that component unmounts. This is helpful if another component will mount soon that will want the same query. That's what Jamie's plugin does: it "caches" the query subscription, staying subscribed to a query after the React component that used it via a useQuery() hook has unmounted.
Clever Tagline
Clever TaglineOP4mo ago
Thanks for that more detailed breakdown. Going back to what started all of this, I guess it's the "caching" of query subscriptions that I feel would be a useful default behavior eventually. As Jamie demonstrated in his demo, it removes a certain amount of "jank" from the user experience, which is never a bad thing IMO.
ballingt
ballingt4mo ago
@Clever Tagline I agree with this. There's some edge case stuff to think about (say you're typing in a textbox that does a type-ahead search; you don't want to hang on to a subscription to all of those queries for "A", "Al", "Ala", "Alam", "Alamo" etc.) that make this not a slam dunk, and you'd probably want to customize this and we don't currently have query options for useQuery(api.foo.bar, args, { staySubscribedFor: 1000 }) — but yes, when we can I'd like this to be automatic. Sometimes this costs you more function executions (you're subscribing to update that your users won't necessarily see!) and sometimes it saves you function executions (instead of unsubscribing and resubscribing, you just stay subscribed) so we'd want to be very transparant about this, but I think this is the right default for a React client. In the TanStack Query adapter for Convex https://docs.convex.dev/client/tanstack-query we made the default stay-subscribed time 30s, configurable as gcTime.
djbalin
djbalin4mo ago
Thanks guys. Yes I was confused by the use of "caching" for Jamie's helper here, even though it may be technically correct. Server-side caching is such a big sell of Convex, and you guys rightfully put an effort into spreading the word, so it kind of becomes a "reserved keyword" that refers to server-side caching of functions as it pertains to Convex. So it confused me a bit seeing the same term used for this conceptually quite different thing! Maybe the header for the section Query caching with ConvexQueryCacheProvider could be elevated to a slightly higher abstraction level and instead describe the outcome or solution to a problem that this provides: persisting subscriptions/keeping server connection alive. The other headers do a pretty good job of being self-explanatory and describing what problem they solve: you get the "nice, I want that.. nice, I want that" feeling when skimming the headers. But not so much with Query caching with ConvexQueryCacheProvider, instead: "wait, doesn't Convex already do that???" Just my 2 cents ☺️

Did you find this page helpful?