Will Server-Side Actions Ever be Viable? They are Ludicrously Slow to Instantiate

Are Server-Side Actions bugged or something? They are too slow to do much of anything interesting.

Take for example, this minimal function in my blockbuster server-side action, “Return 5”:

function(properties, context) {
  return {value: 5}
}

This function takes SECONDS to return the value to the workflow. Seriously, what is up with that? In fact, we can call the same almost-not-even-a-function running on Webtask, through the API connector and get the value back faster.

It’s super-disappointing. My idea with SSAs was to build a ton of nifty workflow building blocks, some of which leverage libraries, but some of which are relatively simple and rely on no libs at all.

However, they all have this ridiculous startup overhead. And, so, you can’t viably chain these actions together in a workflow to d o cool new things… the workflow ends up taking way to long to complete.

And the spin-up time is just insanely inconsistent. Sometimes, an SSA will fire rather quickly. But sometimes it just taaaaakkkkeeeesss reeeeaaaalllly llllloooooonnnggg…

And it’s completely unpredictable. I caught it in the act in this video:

Here’s a demo of “Return 5”: First, we call it over on Webtask via the API connector (pretty darn snappy!). Then we call the SSA “Return 5” directly in response to a button click. Then we call the SSA in a Custom Event workflow fired off by a different button click. Then I do the SSA clicks again…

The first SSA click in this video almost seems like it’s getting hung up… But no, it’s just taking many seconds to complete. And it’s not like, once the function is instantiated that repeated calls to it go faster. It’s just completely unpredictable. Watch:

@Bubble, any input on this? Again, this function literally asks nothing of the properties or context objects and it loads no libs. It just returns with an integer.

This can’t possibly be the design intent of SSAs, can it?

(Also: For anyone wondering – Obviously, this is in a free-level test app. But I get exactly the same type of behavior in my production professional plan app. It’s just miserable.

On the PLUS side: Including even huge NPM libraries does not add appreciably to the spin-up time. It’s totally weird. It’s like, “yeah, we have to wait 20 seconds to return your integer to you, but we can load moment-timezone in 2 ms. Hang on!”)

6 Likes

Just so you can see nothing fancy going on here, here’s the app:

Editor (anyone can view):

Run mode:

Oh, and here’s our friend the SSA, “Return 5”:

Just went through your examples. I have nothing valuable to add, except a concerned, “Yikes.”

5 Likes

Yeah, I’ve built about two dozen insanely cool and useful plugins for doing new and exciting things in Bubble workflows and they are ATM pretty much useless.

2 Likes

Haven’t looked at SSA’s yet, but I tried to offload something to an api workflow yesterday and it took a good 30 seconds to complete compared with 1-2 seconds in the client. I was equally surprised.

API Workflows are limited by your app capacity and are highly variable. They are fine for non-real-time-ish processes. (And highly dependent on what they do. For example, a really simple thing like an API action or Make Change that’s just fetching data from an API is alright and you don’t really notice any ridiculous overhead if you schedule them to run “now”. But I do not use them for iterative data processing stuff – they are just so slow. And recursive API Workflow calls… forget about it.)

Back to SSAs:

The issue with SSA’s is that the promise of them is to build new modular programming components, utilities, etc and being able to move one’s microservices that may be running remotely right now into the Bubble environment.

But at the moment, this seems like a a raw deal. My production app has a number of microservices that run on Webtask when needed, but there’s no benefit in moving them into Bubble right now. Sending large payloads of data out from the API connector to Webtask (where there seems to be extremely generous compute), processing them there and then shipping them back and writing them (as API Ghetto types) happens faster than my de minimus function even returns an integer.

(To which I say, “Umm… what?”)

But stuff like I’m describing above isn’t even what’s exciting about server-side actions. What’s exciting is the prospect of little functional blocks that can be of benefit in any type of workflow (server or client side). But if there’s 3-5 seconds of delay (plus plus at random) for just holding a value or doing a string manipulation, or doing a little trick like moment-based date manipulation, that’s a complete non-starter.

One might assume that custom server-side actions wouldn’t be quite as performant as native Bubble action modules, but one WOULD NOT assume they are several orders of magnitude slower, which is the case right now.

I literally do not get it. SSA’s are a smart move – get people to do more complex and more server-intensive stuff and give them a reason to buy more capacity. But in the present state I see no difference in performance between SSAs on a free app and on a pro plan. (And again, this spin-up problem is a non-starter.)

The weird part about all that is I was worried that the NPM package integration would be the slowdown. But this seems to work instantaneously. There is no performance difference (start-up wise) between an SSA that relies on no node modules, a simple (very small) node module (e.g., Nano ID), or a gigantor node module (e.g., moment-timezone).

So, NPM integration gets two thumbs up. Performance gets two thumbs down. The API to Bubble things is ridiculously overcomplicated and gets a “meh”. (This would also seem to be a problem also with getting started with client-side plugins.)

For anyone reading this who has not explored the data interface to Bubble in the plug-in builder, here’s what’s jacked about the API to it:

  • Essentially you have 4 types of data structures that might be sent to your plugin from Bubble. A thing might be (1) a single object of primitive data type (2) a single object of complex data type (a custom data type from one’s app) (3) a list of single primitive objects or (4) a list of complex objects.

  • These are represented as properties.some_thing.

  • The interface components to one’s function (fields collected by the “Property Editor” for a plugin - the GUI presented to the user) can be used to restrict what types of data the user might send to the plug-in.

  • But there is also a (much appreciated) option to allow “any thing”. So, one’s first order of business is to understand how to get data from an arbitrary properties.some_thing.

  • For no good reason, each of these essentially requires a different method to getting its data. But since properties.some_thing coming from an “any type” input could be one of any 4 of these structures, one first needs to figure out what it is . My first order of business was to write a 40-line helper function for this (figure out what which type this thing might be, check for it being null, and doing common data operations (e.g., get the value(s) in a field of a complex object).

  • The previous bullet point is simply absurd. Why shouldn’t all data objects (even the ones representing primitives) have a .get() method that does this? It’s really baffling – it’s like nobody that would actually build a plugin for Bubble had a hand in designing the API. (At the very least, since this is all a known issue, why isn’t there just a helper function already? Derp.)

  • I will probably publish my helper function here in the Forum once it’s a bit more robust.

Anyway, that’s my early review of Server-Side Actions for Bubble.

Hey @keith, thanks for this useful experience!

When verifying the performance, are you running the server side action in test mode, or have you actually published it? Apparently there can be quite a performance difference between the two, and I don’t know how much it changes server side performance.

EDIT - I just tried running my first server side plugin in Published mode, and it ran just as slowly as before.

@neerja, can you help us with this please? I just invested a week of time in a server side plugin that runs far more slowly than the expectations of my app users would be willing to tolerate. It does some relatively simple search and replaces that take about 2 seconds when done in workflows, but 40 seconds when done in javascript as a server side action. Are server side actions known to run like this? Is there a plan to make the run in more “real time”? This does seem like a “feature” of them that, as app developers, we would like to have been told when the capability was announced!

1 Like

When we test your page @keith we see indeed a 2s execution time. Now as you’re running the plugin in test mode, we can’t do the same kind of caching than we do with published plugins. Can you test with a private, but published version of the plugin?

Hi @emmanuel! Here’s a version of that project where the plugin is not in test mode:

“Return 5 - Mark 2” run mode (live):

“Return 5 - Mark 2” run mode (dev):

And here is its editor:
“Return 5 - Mark 2” edit mode:

I see the same performance issues. BTW, in both my original “Return 5” (is test application for the plugin) and “Return 5 Mark 2” projects, I added cache busting to the Webtask call so that (on repeated clicks) we always ping Webtask rather than returning the cached “5”.

1 Like

@emmanuel: At the moment, I’m seeing the non-is-test-version-of-plug-in version of this project:

… performing pretty well. I haven’t caught it taking 10 seconds for example to return a value. SOMETIMES, one even sees the value come back effectively instantaneously (you don’t even see progress bar), but other times one sees about 4-5 seconds of delay.

I don’t quite understand why or how that happens. (And again, my hope was to be able to chain little actions like this together in a workflow to enable new stuff. For example: 1 Create array of [data type] > 2 Create another array of [data type] > Perform some vector operation on the results of 1 and 2. Maximizing performance becomes a significant issue.)

Anyway, it DOES seem that an app that is not the test version app for a plugin works a bit faster than the one in test mode. But I am still seeing the Mark 2 version (non test) sometimes take 4-5 seconds of progress bar before returning the value.

(The other observation would be that the Webtask API call seems to have less jitter in terms of response time – it’s pretty consistent. The SSA calls will sometimes return immediately and sometimes return in 10 + seconds – in fact, it just saw it do this.)

@emmanuel Here’s a video where I show the random differences (we also see example of a return that takes a Looooong time:

So using server actions consumes capacity, and you’re on a free app. When you run a few workflow one after the other, the last one can be put in waiting mode a bit as capacity has been consumed. Can you release/work on your plugin on an app that is a production app (with potentially additional capacity if you use server actions a lot and confirm). Adding capacity speeds this things up.

2 Likes

Hi Emmanuel,

I fully understand what you’re saying. Here’s sort of a challenging thing for plug-in devs working on server-side actions:

I do have a production app on pro, but I just have 1. So yeah, I could use that as my test app target OR as a check environment for non-test (by giving that app private access to the in-development plugin(s)).

The minimal function I’ve been demonstrating here (which literally just does return {value 5} ) is published so the team can muck around with that as well (it’s called “Return 5”).

I’m actually testing this in my pro plan (default 2 capacity units) app right now and will share a video. But the results are NOT pretty. It’s worse than a free app.

This SSA – which again DOES NOTHING – seems to consume 30 - 50% of my available capacity.

Really? Video to come.

Hey @emmanuel, thanks for coming into the conversation! Would you be willing to take a look at my situation too, as mine has some real code doing some real work. I’ll pm you how to log on and try it.
Thanks in anticipation!
Antony.

Please do this via a bug report, that’s better.

Thanks

No problem, I’ve already got one filed on this issue.

Done. Thanks for your input! :slight_smile:

There’s a pretty big improvement here. I have noticed what might be a couple of bugs, which I’ll report via bug report after looking a little deeper. Thanks for this!!

We’ve pushed a fix which should be live now.