Add Concurrency Control to Backend Workflow Mutations

This is a correctness and data-integrity issue that can easily cause dropped production data, so it’s not merely a nice-to-have.

The problem:

Bubble has no built-in way to serialize backend workflow actions that mutate the same record (that I know of), causing race conditions.

When instances of a “Schedule API Workflow on a List” run against the same parent Thing, the runs race each other, and Bubble can and will drop data as a result (even when runs have a 1+ second interval gap).

This is not something I run into rarely. Each time, I realize data has been dropped due to the lack of concurrency safety or control when mutations are made around the same time to the same objects in the database, which causes a given mutation to not be applied and leads to a bug for the end-user.

Concrete example:

I have a workflow that processes a batch of items by scheduling a backend workflow once per item, each of which:

  1. Creates a new child record
  2. Then updates a shared parent record by adding the new child to one of its list fields

Even with a 1-second gap between runs, two runs executed close together (21ms apart, in one observed case).

In this case, both created their child record successfully, but both also tried to add themselves to the parent’s list at nearly the same time, and one write overwrote the other (race condition). One child record was created but never got attached to the parent’s list, making it permanently invisible in the app even though it exists in the database. In this real case, it caused a set of buttons to not work because the child answer object wasn’t found on the parent questionnaire list.

Why this is urgent:

  • This isn’t an edge case you can work around cleanly or easily. It’s a fundamental gap in how Bubble handles concurrent mutations to the same Thing. Any app that fans out backend workflows against a shared parent record is exposed to this.
  • The only “solution” available today is guessing an interval between scheduled workflow runs that’s long enough to avoid overlap consistently. That’s not a fix, it’s bad-practice trial-and-error by guessing at execution time, which varies. There’s really no 100% reliable number you can pick, and what works today can silently start failing again later.
  • Worse, it fails silently. There’s no error, no log entry flagging a conflict — you just quietly lose data. Teams may not know this is happening until a user reports something missing, by which point it’s already affected production data.

Solution:

Either:

  1. Native support for developers to explicitly lock/serialize an action against a given Thing (a mutex/critical-section) so overlapping workflow runs queue/wait instead of racing, or
  2. Bubble’s own “Change Thing → add to list” (and similar list-mutating) actions become atomic/serialized at the platform level by default, so this class of bug simply can’t happen regardless of how workflows are scheduled.

You should read the Monthly Community Update - August 2026

Also, in most case, if you give the correct interval, you will not race into this issue.

However, there’s room for improvment, I totally agree!

Thank you for linking that—very helpful.

I definitely realize this issue has been discussed in past posts on the forum, but I haven’t heard of or found a concrete fix for it, so this is good to hear.

I think one of the most discussed topics here is race conditions and concurrency, I think for advanced apps, Bubble MUST implement a way to protect us from this.

Last year I had a customer trying to use Bubble for banking, balance, statements and some web hooks and it was crazy how I could not protect the database from race conditions.

I remember we needed to keep a consistency serial number, if we need to start with 01 the next should be 02 and can’t be sent again, and Bubble could not make it safe, I used the method " :make static "and finally the system had some alternative but most of the features I could not use Bubble at all.