About order of operations in workflows and best practices

As everybody should do, I read this fundamental thread about Order of Operations in Workflows.
In his reply @aschofer among other interesting things says:

In a workflow with two actions, if Step 2 is using a condition based on a search depending on data manipulated in Step 1, then Step 1 should be implemented into a custom event to make sure it is finished before moving on to Step 2.

Well in my experience this, unfortunately, is not completely true. Let me explain.

Here’s the public app (I hope it works, first time I share an app)

CASE: in a WF I want to modify a field in the database and, as a result, set a value to a custom state.

SOLUTION 1, the WRONG one (it’s here for explanation sake)

I click the button that triggers the WF, but step 2 is (or better: could be) faster than step 1 and no value is assigned to the custom state.

SOLUTION 2. The one suggested by @aschofer

Also this solution unfortunately is not consistent, sometimes step 2 is executed before the completion of step 1.

SOLUTION 3. The only one giving consistent results.

As you can see I activate a “ping-pong” loop…

ending when it’s sure that the value in the Database has been updated.


I’m a little deceived by this behaviour and I think that an event like “wait until condition is met” should exist.
I think that solution 3 is, anyway, the best option if we want to be sure that there will be no surprises.

And in the end, coup de theatre!

To further complicate things if you play with the app you’ll notice that:

  • if you click trigger1 → reset → trigger1 ==> the 1st time everything looks fine but from the 2nd the CS is not updated (empty field).

  • Same behaviour for button trigger2

  • button trigger3 works all the time

  • BUT (and here I get mad) if you activate buttons trigger1 and/or trigger2 AFTER clicking trigger3 THEY ALWAYS WORK. (Bug? My mistake?)
    (Refresh the page and you will see again the described behaviour).

If I did something wrong in this simple app please let me know, my mental sanity depends on this at the moment. Thank you.

1 Like

What if you in Solution 1 set the condition to “when step 1 is not empty”. That should force the execution of step 1 prior to step 2 since step is depending on step 1.

If I remember correctly, Bubble said that Solution 2 should be a way to control WF execution flow (from an earlier post discussing the asynchronousness of WFs.

Best, Peter

1 Like

Thank you Peter, looks like a simple solution, I’ll test it.

Ok test done, it doesn’t work.

What I think happens is that step 2 is executed after step 1, true.
But too fast, and since step 1 is longer to execute, step 2 is solved before that the database is modified.

The problem here is that I know that a field in the database will be modified as I expect; what I want the app to do is waiting long enough to find that field modified.

Kind of “enter the room as soon as the light will be switched on”.

You mean that having Step 2 to needing input from Step 1 did not make Step 2 wait? That would have some serious effects.

1 Like


I also tried on one of my projects, much more complex than the simple example I created for this topic, and actually the only solution that always works, so far, in number 3 (the ping-pong technique).

I agree that the effects are serious and have to be kept in mind.

As @aschofer wrote:

Frontend workflow actions run in order but the next action does not wait on the previous action to be complete before triggering

This means that some more time consuming actions (database manipulations, conditional actions with a search with filters, backend workflows), even if triggered before will end much later than a simple action such a custom state set value (they actually do).

Hi @gallahad11,

It’s also well-described in the documentation.

SOLUTION 1 looks like the right solution to me IF, as @philledille says, step 2 references step 1 (makes it a dependency). That’s the way Bubble should work and the way it has worked for me.

If you have a reproducible example where that’s not the case, you should file a bug report. You shouldn’t have to jump through hoops to accomplish what you’re trying to do.

1 Like

Hi @sudsy,
thank you for taking the time to reply to my post.

Well I don’t really think this behaviour is a bug, rather something (annoying) to keep in mind.

All the 5 workarounds suggested in the documentation are, really, workarounds. Also what I called the “ping-pong” technique is a (painful but not impossible) workaround.

Thinking that the “Result of step X” operator creates a dependency, as far as I understand, is a mistake: it doesn’t mean “wait for previous step to be finished”, but rather “take the values I sent to the database directly from the previous step without the need to search the database [that will be updates asap, but maybe later than you expect]”.

This makes a huge difference, especially if what you are interested in is not the data passed to the database, but a condition that becomes true when that database record is modified.

1 Like

2 things to keep in mind:

  • That’s what database triggers are for.

  • Bubble is event driven and has a “reactive” front end baked into the platform; so depending on the problem you’re trying to solve, you might not need to set a state at all. Data that’s dynamically referenced in the UI (from the front end), for instance, will automatically update when the underlying value changes. (It’s not uncommon for folks with a bit of traditional coding background to approach Bubble with more of a “procedural” mentality and thus try to “force” execution order or use workflows when it’s not really necessary.)

1 Like

Another way is to use Terminate with a condition, since the actions after the Terminate don’t know if they should be executed or not until the Terminate’s condition is resolved.

1 Like

Maybe it’s me missing something, and I’ll be happy to learn from this discussion.

There are 2 important statements taken from the documentation:

Statement A

Searches aren’t always immediately updated with new data. So if you create a new item, and then try to retrieve it via search, it may or may not work; you should not rely on this.


Statement B

We do not offer the explicit ability for an action to wait for a workflow to be over before moving on to the next step; however, using ‘add a pause before next action’ action is usually an effective workaround

Sometimes I see conditions considered as a way to put an action on hold until the condition is met. As far as I understand the truth is that things will happen without delay either way, the only difference being the fact that the action has been executed or not.

Statement A always has to be kept in mind, in my experience especially as single page apps grow: this is when I think the app itself can become slower and record changes experience delays.

Statement B is clear enough: a delay is not possible out of the box. A simple workaround is waiting a fixed amount of time, but this is not enough if you want to be 100% sure that things happen the right way (it’s not a “wait until…”
Hence the “ping-pong” solution.

I’m also testing

  • Trigger a custom event when data changes: no luck so far;

  • WF with Do when condition is true trigger: under testing, fingers crossed.

This will either (1) stop the workflow or (2) continue its execution (without waiting for the condition to be true).

In case (1) nothing happens, but since in my case the WF is triggered by a button that registers to the database the value of an input field, the client doesn’t see anything happening. And this is not acceptable.

In case (2) things will happen, perfect: it means that the control database record has been updated BEFORE the execution of the terminate action.

This solution appears to be working. This is good news indeed.

The truth is that we [nocoders with average experience, I’m not talking of gurus] have to consider all of this or some functionalities of our apps won’t work properly.

Hi @gallahad11
I’ve just checked the documentation about workflows, and I found this workaround:

In a workflow with two actions, if Step 2 is using a condition based on a search depending on data manipulated in Step 1, then Step 1 should be implemented into a custom event to make sure it is finished before moving on to Step 2.

This way you’re sure the changes have made before used them in a custom state.
That means solution 2 from @aschofer is right :wink:

Hope this helps :wink:

1 Like

Hi @mickceb

believe me or not, but this was the first solution I tried and, in my app, didn’t work as expected.

I’ll reset all the workflows and start from scratch, maybe after too many corrections something under the hood is wrong and prevents things to work properly.
I’ll post something ASAP.

@gallahad11 I’ve just checked your app and I don’t understand what value you want to pass to custom state (as shown below)
What’s “amount - deleted” ? There is no corresponding field in a DB.

my fault, during this discussion I modified the app, deleted fields and unfortunately now is not working. I’ll do my best to correct this in the next minutes.

1 Like

ok it’s at its original state. Sorry again for making you lose time.

1 Like

@gallahad11, I tested your app with the debugger and all work well :wink:
It seems solution 3 is the faster following by second one.

@mickceb did you try:

  • refresh page
  • click trigger1
  • click button reset
  • click trigger1

the second time you click the trigger1 button, do you see the active text appearing? (I don’t)

I clicked button and reset multiple times and each time “active” appears.
Have you tried with another device?