# Async Execution and Blocking in Ignition

**URL:** <https://forum.inductiveautomation.com/t/async-execution-and-blocking-in-ignition/115410>\
**Category:** Ignition\
**Tags:** scripting\
**Created:** [May 6, 2026, 4:28pm UTC](https://forum.inductiveautomation.com/t/async-execution-and-blocking-in-ignition/115410 "2026-05-06T16:28:23Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![keithms](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/keithms/32/58243_2.png) [@keithms](https://forum.inductiveautomation.com/u/keithms)\
**Post date:** [May 6, 2026, 4:28pm UTC](https://forum.inductiveautomation.com/t/async-execution-and-blocking-in-ignition/115410/1 "2026-05-06T16:28:23Z")

</div>

I recently was made aware an issue that got me thinking about scripting in asynchronous contexts in Ignition.

In this case, blocking functions such as `sleep` and `system.tag.writeBlocking` were being used in tag event scripts and appeared to be causing problems.

The proposed fix was to move that work into `system.util.invokeAsynchronous`.

The recommendation implied a few things to me, based off my experience with other languages and async runtimes:

- Tag event scripts execute in a shared execution context with other scheduled tasks.
- Blocking operations in that context can prevent other scheduled tasks from making progress.
- `system.util.invokeAsynchronous` is intended to offload long-running or blocking work onto a thread pool where blocking is acceptable, so that the original execution context can continue.

In general, the main reasons I would expect to want to block a thread are:

- Expensive CPU-bound work
- Synchronous I/O

Those are the situations where I would expect to reach for something like `system.util.invokeAsynchronous`.

My questions are:

1. Are my assumptions sound?
2. If so is there documentation or guidance describing which Ignition scripting contexts users should avoid blocking in?
3. Is there a need for more general education around this topic: what blocking means, when it is acceptable, and what are the strategies for managing blocking tasks?

One related thought I have is if the idea "write a value and wait" is a common anti-pattern. My understanding is that `system.tag.writeBlocking` waits for the write operation itself to complete, but that does not necessarily mean the new value has already been published back through the tag system. If a script then sleeps for some guessed amount of time hoping the value will update, that seems fragile. Even if that logic is moved to a thread where blocking is acceptable, it also seems like it could become problematic if many of these tasks stack up.

I would appreciate any clarification. I suspect part of my confusion is trying to map concepts from other runtimes/frameworks onto Ignition without fully understanding how Ignition manages these execution contexts internally.

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [May 6, 2026, 5:01pm UTC](https://forum.inductiveautomation.com/t/async-execution-and-blocking-in-ignition/115410/2 "2026-05-06T17:01:31Z")

</div>

> [@keithms](#):
>
> causing problems

Yes. Some detailed [reading for you](https://forum.inductiveautomation.com/search?q=%40pturmel%20tag%20events%20thread%20pool%20order%3Alatest).

Key points:

- Tag events (defined on the tag) run in a pool of three threads, by default. If you have three event scripts simultaneously sleeping or waiting on the network (DB, OPC, web APIs, whatever), all other tag events will stall.

- `system.util.invokeAsynchronous` can solve the above, but launching threads is not a light-weight operation, and you can fill RAM with stalled threads. Extensive CPU bound work is a good reason to use a separate thread. Synchronous I/O _usually_ is not.

1. Your assumptions are close.
2. Not really. Except here on the forum. The docs do mention the per-tag queues and the missed events flag, which **implies** limitations on tag events.
3. It would be nice if there were good guides for selecting tag events versus gateway tag change events. (The latter use one thread and only one thread for the given list of tags, and are independent of other thread pools.)

> [@keithms](#):
>
> idea “write a value and wait" is a common anti-pattern

Yes. Looping or waiting in a thread for some signal to change is very much an anti-pattern. The wait should be re-engineering into another tag event or tag change event, with a state machine to indicate what applies when. No waiting.

All that said, there are some things that are fine in tag events:

- `system.tag.readBlocking()` to collect values from a bunch of other tags. This is near instant, as only current values are retrieved. The "blocking" aspect is that you get the results synchronously.
- `system.tag.writeBlocking()` when the target is a **memory tag**. (Or multiple memory tags.)
- `system.tag.writeAsync()`
- `system.db.runSF*()` to queue updates in the Store and Forward system.

---

<div class="post-metadata">

**Author:** ![keithms](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/keithms/32/58243_2.png) [@keithms](https://forum.inductiveautomation.com/u/keithms)\
**Post date:** [May 8, 2026, 1:18pm UTC](https://forum.inductiveautomation.com/t/async-execution-and-blocking-in-ignition/115410/3 "2026-05-08T13:18:57Z")

</div>

Thank you as always Phil. I always appreciate your insightful answers, and how you respond in a way that doesn't discourage me from asking questions in the first place.
