# Slow Expression Tags

**URL:** <https://forum.inductiveautomation.com/t/slow-expression-tags/99527>\
**Category:** Ignition\
**Tags:** ignition81\
**Created:** [December 6, 2024, 3:13pm UTC](https://forum.inductiveautomation.com/t/slow-expression-tags/99527 "2024-12-06T15:13:39Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![dominicfabiilli](https://avatars.discourse-cdn.com/v4/letter/d/c6cbf5/32.png) [@dominicfabiilli](https://forum.inductiveautomation.com/u/dominicfabiilli)\
**Post date:** [December 6, 2024, 3:13pm UTC](https://forum.inductiveautomation.com/t/slow-expression-tags/99527/1 "2024-12-06T15:13:39Z")

</div>

Version 8.1.39

I was working on a customer's server when I noticed that expression tags were taking 30-40 seconds to initialize or to update their values.

I tried creating memory and reference tags and those updated immediately.

All of these tags were on my own tag group which had the default settings of 1000ms and a new name to differentiate from "Default".

Remoting into the server showed the cpu was consistently around 40% and the memory allowed for Ignition is 12 of 32GB. Ignition is only using a max of 9GB.

I am curious to know how expression tags execute differently from other types. And I want to know if anyone has seen and/or remedied this behavior before.

Some other information:

- there are 2 other tag providers that have about 50k tags each
- otherwise there around 10k tags among 10 other providers
- this gateway has the MQTT transmission module

---

<div class="post-metadata">

**Author:** ![Kevin.Herron](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/kevin.herron/32/7259_2.png) [@Kevin.Herron](https://forum.inductiveautomation.com/u/Kevin.Herron)\
**Post date:** [December 6, 2024, 3:14pm UTC](https://forum.inductiveautomation.com/t/slow-expression-tags/99527/2 "2024-12-06T15:14:54Z")

</div>

If it's still happening get a thread dump and post it here.

> **[Diagnostics - Threads | Ignition User Manual](https://docs.inductiveautomation.com/docs/8.1/platform/gateway/status/diagnostics-threads#individual-threads)**
>
> The Threads page displays a snapshot of information about Gateway’s execution threads. This information may be important when troubleshooting certain types of issues. If you are working with Support, you may be asked for a thread dump.

---

<div class="post-metadata">

**Author:** ![dominicfabiilli](https://avatars.discourse-cdn.com/v4/letter/d/c6cbf5/32.png) [@dominicfabiilli](https://forum.inductiveautomation.com/u/dominicfabiilli)\
**Post date:** [December 6, 2024, 7:39pm UTC](https://forum.inductiveautomation.com/t/slow-expression-tags/99527/3 "2024-12-06T19:39:36Z")

</div>

Ok here it is. Thanks

[Ignition-JOPV9903\_thread\_dump20241206-143716.json](https://forum.inductiveautomation.com/uploads/short-url/fXb20uspMxopJLqTgSdvjNq2cG6.json) (555.7 KB)

---

<div class="post-metadata">

**Author:** ![dominicfabiilli](https://avatars.discourse-cdn.com/v4/letter/d/c6cbf5/32.png) [@dominicfabiilli](https://forum.inductiveautomation.com/u/dominicfabiilli)\
**Post date:** [December 6, 2024, 7:42pm UTC](https://forum.inductiveautomation.com/t/slow-expression-tags/99527/4 "2024-12-06T19:42:43Z")

</div>

Sorry, use this one. This is while it was executing.

[Ignition-JOPV9903\_thread\_dump20241206-144026.json](https://forum.inductiveautomation.com/uploads/short-url/AiV36QtWtz5k66vZTRS37GDJxEq.json) (580.4 KB)

---

<div class="post-metadata">

**Author:** ![GeraldB](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/geraldb/32/36210_2.png) [@GeraldB](https://forum.inductiveautomation.com/u/GeraldB)\
**Post date:** [August 6, 2025, 11:56am UTC](https://forum.inductiveautomation.com/t/slow-expression-tags/99527/5 "2025-08-06T11:56:34Z")

</div>

Same behaviour for me. Im am using Ignition 8.1.36  
Is there a solution for that?

---

<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:** [August 6, 2025, 12:06pm UTC](https://forum.inductiveautomation.com/t/slow-expression-tags/99527/6 "2025-08-06T12:06:15Z")

</div>

The most common cause is use of `runScript()` in expression tags where the scripts aren't executing quickly (~10ms or less).

Like tag event scripts (on tags, not in projects), expression tags execute in a dedicated thread pool of size three. As soon as you have three slow expressions running, all other expressions (in the whole gateway) have to wait.

All of the constraints discussed on this forum for tag event scripts also apply to expression tags' `runScript()` calls.

---

<div class="post-metadata">

**Author:** ![GeraldB](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/geraldb/32/36210_2.png) [@GeraldB](https://forum.inductiveautomation.com/u/GeraldB)\
**Post date:** [August 6, 2025, 2:46pm UTC](https://forum.inductiveautomation.com/t/slow-expression-tags/99527/7 "2025-08-06T14:46:50Z")

</div>

Thanks for the answer. I added a few more threads (described [here](https://www.docs.inductiveautomation.com/docs/8.1/appendix/reference-pages/gateway-configuration-file-reference/gateway-and-gateway-network-parameters)).

We now have ~150k tags on that server, thus i think it makes sense to increase the number of threads. `runScript()` is not that often used but there are a lot of expression tags.

Best Regards,  
Gerald

---

<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:** [August 6, 2025, 3:09pm UTC](https://forum.inductiveautomation.com/t/slow-expression-tags/99527/8 "2025-08-06T15:09:38Z")

</div>

Yes, that's a lot of tags. If the increased thread pool doesn't help, you should open a support ticket and give IA a thread dump to examine.

---

<div class="post-metadata">

**Author:** ![Kishan](https://avatars.discourse-cdn.com/v4/letter/k/e95f7d/32.png) [@Kishan](https://forum.inductiveautomation.com/u/Kishan)\
**Post date:** [February 21, 2026, 11:38am UTC](https://forum.inductiveautomation.com/t/slow-expression-tags/99527/9 "2026-02-21T11:38:39Z")

</div>

I recently ran into the same issue. I would have an opc tag that would update immediately, but I used an expression tag to first validate the quality of the OPC tag before using it and go to a failover if the quality is bad. I also have a lot of runScripts in expression tags. My tags would update very slowly.

I have been working on reducing my use of this. One of the things I have been doing is putting the opc tag quality validation in my view logic, instead of in tags. But in some cases, an expression tag really is the best way to go as far as I can tell.

So in the case that I still end up using a high amount of expression tags and runScripts, the best way would be to increase the thread count based on this discussion.

How do I know the amount of threads I can increase by? I have never done this so I’ll have to look into that link that Gerald added. Thank you by the way!

And are there ways to improve this other than adding more threads?

---

<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:** [February 21, 2026, 4:13pm UTC](https://forum.inductiveautomation.com/t/slow-expression-tags/99527/10 "2026-02-21T16:13:20Z")

</div>

> [@Kishan](#):
>
> I also have a lot of runScripts in expression tags.

Fix this. Really.

If you have lots of them, then adding more threads will simply tie up more threads.

---

<div class="post-metadata">

**Author:** ![Kishan](https://avatars.discourse-cdn.com/v4/letter/k/e95f7d/32.png) [@Kishan](https://forum.inductiveautomation.com/u/Kishan)\
**Post date:** [February 21, 2026, 7:32pm UTC](https://forum.inductiveautomation.com/t/slow-expression-tags/99527/11 "2026-02-21T19:32:19Z")

</div>

Yup, I have been reducing them. So general consensus is to use runscript functions as little as possible?

---

<div class="post-metadata">

**Author:** ![michael.flagler](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/michael.flagler/32/26272_2.png) [@michael.flagler](https://forum.inductiveautomation.com/u/michael.flagler)\
**Post date:** [February 21, 2026, 7:40pm UTC](https://forum.inductiveautomation.com/t/slow-expression-tags/99527/12 "2026-02-21T19:40:58Z")

</div>

In general yes. I use them very sparingly and only for things like string lookups or formatting where I have a number that is like a fault code on a VFD and I lookup the associated name/description of the fault.

---

<div class="post-metadata">

**Author:** ![Kishan](https://avatars.discourse-cdn.com/v4/letter/k/e95f7d/32.png) [@Kishan](https://forum.inductiveautomation.com/u/Kishan)\
**Post date:** [February 21, 2026, 7:56pm UTC](https://forum.inductiveautomation.com/t/slow-expression-tags/99527/13 "2026-02-21T19:56:52Z")

</div>

This is what I have been using it for as well. To be able to refer to tags using wildcards.

But going back to the original topic. Expression tags in general should then also be avoided?

---

<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:** [February 21, 2026, 8:05pm UTC](https://forum.inductiveautomation.com/t/slow-expression-tags/99527/14 "2026-02-21T20:05:45Z")

</div>

> [@Kishan](#):
>
> runscript functions as little as possible?

Yes. Where you must use them, you should time them with `java.lang.System.nanoTime()` and log when \>5ms. So you can focus on removing the worst offenders.

Ideally, do not run database or network operations, or make system calls that do database or network operations.

Make sure the tags are in event driven mode, so they only run when a reference changes.

> [@michael.flagler](#):
>
> I lookup the associated name/description

This should not be in an expression tag at all. It will run when no one is looking at it (useless), and cannot be internationalized for multiple simultaneous users. This belongs in UI bindings.

> [@Kishan](#):
>
> refer to tags using wildcards

This is a heavy operation. Avoid tag searches except where a user triggers it.

> [@Kishan](#):
>
> Expression tags in general should then also be avoided?

No, expression tags in general are fine, and useful in a variety of cases.

---

<div class="post-metadata">

**Author:** ![nminchin](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/nminchin/32/6911_2.png) [@nminchin](https://forum.inductiveautomation.com/u/nminchin)\
**Post date:** [February 23, 2026, 1:42am UTC](https://forum.inductiveautomation.com/t/slow-expression-tags/99527/15 "2026-02-23T01:42:39Z")

</div>

> [@pturmel](#):
>
> > [@michael.flagler](#):
> >
> > I lookup the associated name/description
> 
> This should not be in an expression tag at all. It will run when no one is looking at it (useless), and cannot be internationalized for multiple simultaneous users. This belongs in UI bindings

I’m not sold on this. Consider you have multiple valve devices that have slightly different status enums resulting in value 1 for example being a different state of the valve for each. (this can happen over time as code is improved, or if you’re incorporating another integrator's plc code).

If you use an expression tag, it's extremely simple to create UDTs for each of the valves and have a unique status descriptive tag for each valve, where 1 results in a different value for each. Then your UI becomes detached from the raw values of the valve tags, because you can simply use the standard descriptive tag values which are all standardised. Eg with states “Opened”, “Closed”, “Opening”, etc. Rather than looking at a status enum value which might represent different things as in my example.

If I instead do the enum lookup in the UI, I now have a _ **lot** _ more work to do with significantly higher risk of mistakes and maintenance. I either need to have a huge case statement first looking at the UDT Type, then another which maps the enum value to the state, which all needs to be done everywhere you want to use or show the status descriptive text 💀; or I need to have a template view for every single UDT which does the enum mapping in that 💀💀

Maybe I'm missing something?

---

<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:** [February 23, 2026, 1:52am UTC](https://forum.inductiveautomation.com/t/slow-expression-tags/99527/16 "2026-02-23T01:52:38Z")

</div>

> [@nminchin](#):
>
> slightly different status enums

I'd call that design error #1.

> [@nminchin](#):
>
> Then your UI becomes detached from the raw values of the valve tags

Until you need a second or third language, and you are screwed.

And you are still processing string lookups for many tags that aren't being watched.

For such a poorly designed project, I would construct a **shared** document tag with two layers of keys--outer enum "type" and inner state value to lookup. I would ensure the result strings were unique translation keys. Then any tag value that needs lookup and translation can just have custom tag property indicating the enum "type" for lookup.

UDTs stay lean. Lookup values are centralized. No excess computation is performed.

---

<div class="post-metadata">

**Author:** ![nminchin](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/nminchin/32/6911_2.png) [@nminchin](https://forum.inductiveautomation.com/u/nminchin)\
**Post date:** [February 23, 2026, 1:54am UTC](https://forum.inductiveautomation.com/t/slow-expression-tags/99527/17 "2026-02-23T01:54:31Z")

</div>

> [@pturmel](#):
>
> For such a poorly designed project

Sometimes you cant help it when you’re incorporating programmes from multiple OEM's who have fixed code

---

<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:** [February 23, 2026, 1:55am UTC](https://forum.inductiveautomation.com/t/slow-expression-tags/99527/18 "2026-02-23T01:55:26Z")

</div>

Certainly. Or rescuing a disaster. That's why I made a concrete suggestion.

---

<div class="post-metadata">

**Author:** ![nminchin](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/nminchin/32/6911_2.png) [@nminchin](https://forum.inductiveautomation.com/u/nminchin)\
**Post date:** [February 23, 2026, 2:29am UTC](https://forum.inductiveautomation.com/t/slow-expression-tags/99527/19 "2026-02-23T02:29:35Z")

</div>

(sorry got a phone call as I was replying)

Sounds like a great way to do this though while still maintaining the centralised approach that is also maintainable, while also minimising impact on the gateway. Would you do the same if you're expecting large numbers of clients connected at once? Eg 150 or so

---

<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:** [February 23, 2026, 2:32am UTC](https://forum.inductiveautomation.com/t/slow-expression-tags/99527/20 "2026-02-23T02:32:58Z")

</div>

Yup. It's all in the gateway. The expression language bracket syntax to extract values from document tags appears to be super efficient.

[Next page](https://forum.inductiveautomation.com/t/slow-expression-tags/99527.md?page=2)
