Using actions as queries
I have a few queries that require node (specifically the rrule library, and probably date-fns), so I'm working on using actions for them. Any reason this would be considered an anti-pattern? Any pitfalls to look out for when using actions this way?
12 Replies
First things first, Convex wants to make sure there's a way to do anything, because there are always exceptions to the rule, and we're realists 😄
in general, you should strive to always have queries be the things you're attaching application state to
1. actions are not automatically subscribable or automatically cached. so you'll have to poll the action "periodically" or when you know the results are invalidated to keep your app fresh
2. the consequences of (1) mean that your app may sometimes show UI state that is inconsistent. Convex (and the react client) gurantee that all your components will stay fully consistent, and update together when dependent data has changed. Whatever UI state is dependent on your action will not have this guarantee, and so therefore has the ability to reflect older or newer backend data (in practice almost always older, it's very hard to beat the update speed of Convex's query runtime) in a way that contradicts the rest of your app from time to time
3. there is a lot of "pit of success" (things that go better than anticipated as your project grows) around Convex's design with regards to queries and mutations -- things like iterative development, cache coherency, backend composability. You're on your own in general a lot more when you manage your own reads, which is what you end up having to do with actions on the read path
4. actions can fail, and the Convex client will not guarantee they re-run. with queries, you can pretty much ignore transient failures because Convex, like the terminator, will just... keep... going until it pulls the whole world forward for all queries. With actions, not so -- your app could essentially "freeze" in a loading state if one of these read-actions fails
basically, reading on actions takes you back to the way the rest of the Internet works besides convex: a lot worse 😄
however, sometimes it is necessary. if this is the case for you, give it a whirl and let us know if you run into any problems.
in our experience, the alternative way to usually solve the general need you've expressed here is to reflect the heavier-compute or effectful value in the database on the write path and let the query dispatch system do its thing on all read paths
meaning, whatever you need to do that involves libraries that don't run in the convex runtime, try to structure your app to run your action on the write path once, and store the computed outcome in a mutation so you're still relying on pure queries for dispatching application state. this is in general going to lead to better apps and easier to reason about debugging and so on
but if that's not possible, yes, you can read from an action
long answer, but hope that helps!
That's exactly what I needed, thanks for writing that out. Completely forgot some of those caveats around actions, I'll see if I can push the npm module dependent computation to the client.
I know a few libraries have been cleared for use in your custom environment - is there a way to determine if other libraries may also work there or are those libraries (lodash, bignumber, etc) on a strict allowlist?
rrule and date-fns don't have dependencies, so I'm wondering if there's a chance they'll run. Guess I could just try lol
good chance they'll run! we're expanding support for modules all the time
@erquhart I was going to ask what error do you get when you use rrule in the Convex runtime — a lot of dependencies just work! Trying it now to see.
as long as they don't requires fetch etc, most things work these days
ooh nice, I'll try these two and let you know
rrule looks good!

That is amazing news, I didn't realize trying libs in the convex env was even an option
re
is there a way to determine if other libraries may also work there or are those libraries (lodash, bignumber, etc) on a strict allowlist?- if it requires a compiled C++ Node.js extension it's not going to work (although check if the library provides a JS-only fallback) - if the library is written exclusively fo Node.js and doesn't work in the browser or other edge runtimes, it probably won't work; the Convex runtime doesnt' expose the
fs
module for example
The other thing to know re just trying dependencies is that the runtime will fail loudly (throwing an uncatchable exception) if it can't provide a spec-compliant implementation of something, so you should be safe trying things out.
We do want to hear about dependencies you need that don't work, it's not impossible to find them! Often the problem is bundling or the library is doing capability checks that make it assume the environment incorrectly.Got it, thanks for the details! I've been doing a lot of heavy lifting right in the client - it sounds like libraries that can run client side are pretty likely to work in the convex environment, so that's a bit of a game changer. Convex makes backend feel like a very close extension to the client, so I'm moving more and more to the server now, and this definitely helps.
yep! if it works in the browser, good chance it will work in the convex runtime too. and if it won't, we'll tell you. give it a shot and let us know if everything works out
Update: works amazingly 💫