How can I synchronize multiple calls to the same webhook to prevent race conditions?

Describe the problem/error/question

I’ve checked the forums and the documentation, but can’t find the answer to my question:

  • I can see that - in production - if a webhook is called while another webhook is still busy, the second webhook just starts running too
  • I assume that this is a different job with different input data
  • Both jobs/flows write to the same database: I assume the database (CrateDB) will take care of the locking

But what about writing to a file? I append incoming data to a csv file. It is not clear to me what happens if both jobs/flows start to append data to this file at nearly the same time.

In other words: can I serialize these calls at some point in the flow, a sort of semaphore or something like that?

I’m running a default Docker installation. No workers orso.

Information on your n8n setup

  • n8n version: 1.80.4
  • Database (default: SQLite): default
  • n8n EXECUTIONS_PROCESS setting (default: own, main): default
  • Running n8n via (Docker, npm, n8n cloud, desktop app): Docker
  • Operating system: Ubuntu LTS
  • Web/SSL Proxy in front of n8n: Caddy

You might need a way to queue the calls or configure concurrency rules.

Please see these documentations:

A smiliar workaround would be to store each request in a temporary database table, and process only one request at a time. It would be like building the features from the documentation above, but using a worse approach :sweat_smile:

:point_right: If my reply answers your question, please remember to mark it as a solution.

Hmmm.

I did read that documentation, but it is still unclear to me:

  • a worker does one job at a time? So using one Main and one Worker (queue mode) would automagically queue webhooks?
  • the concurrency control is a bit clearer: if I would set that one to “1”, then every webhook is queued if that webhook is running? So the worker can only process a single webhook job at a time?
  • What if I have 4 different webhooks and use queue mode. Are those webhooks handled concurrently, or one at a time?

So, there are no possibilities to configure the concurrency of the webhook itself? Some webhooks may run concurrently, and some not.

If you could configure concurrency, one could process multiple webhooks if possible, and (from that flow) post to a “single” webhook where it matters, ie all other concurrent running webhooks will get queued automatically.

The webhooks are fired from Azure EventGrid (there is no node for Azure EventGrid / Blobs / Etc).
I know EventGrid will do retries, but I try to avoid that as the order of events gets mixed up in that case.

Thanx for that hint using Kafka or something else that can implement a FIFO queue! MQTT and Redis should be able to implement this.

As a follow-up, I’m currently leaning towards a simple Redis List for real-time processing or batch processing. Both are supported by n8n.

Real-time Flow 1:

  • HTTP trigger event from Azure
  • Add the event to the Crate database.
  • Then push the event to a Redis List, acting as a FIFO queue
  • Return HTTP call

Real-time Flow 2:

  • Pop events from the Redis List
  • Process the event
  • Get the next item from the Redis list

Even if new events are coming in during the “Real-time Flow 2” processing, events are still processed sequentially. No race-conditions anymore.

With this solution, I can use a simple single n8n docker container, but also have a mechanism that works if I have multiple running webhooks that should be processed sequentially.

As Azure EventGrid might deliver events out of order, they advise using a small delay in the processing part. That should be solved by batch processing incoming events.

Batch-like Flow 1:

  • HTTP trigger event from Azure
  • Add the event to the Crate database.
  • Return HTTP call

Batch-like Flow 2:

  • Get events from the database every 5 minutes with an advised delay of 2 minutes, ie, get events which are at least 2 minutes old
  • Process the event
  • Get the next event from the database

In this way, the actual event handling is always sequential and guaranteed in the order of incoming events if I sort the database on the datetime field supplied by Azure EventGrid (the time the event was generated).

And as an alternative to the above:
Use the BullMQ community node that uses Redis as the underlying platform to queue messages and process them, either one-by-one or concurrently.

Hmmmm. Decisions :grimacing:

Nice… I somehow answered a question in a different thread just by linking to it as an example of the same question being sorta unanswered yet. Glad it helped.