# Trying to get better Graph performance

**URL:** <https://forum.inductiveautomation.com/t/trying-to-get-better-graph-performance/115219>\
**Category:** Ignition\
**Tags:** perspective\
**Created:** [April 23, 2026, 5:33pm UTC](https://forum.inductiveautomation.com/t/trying-to-get-better-graph-performance/115219 "2026-04-23T17:33:31Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![joshua.edwards.navy](https://avatars.discourse-cdn.com/v4/letter/j/b19c9b/32.png) [@joshua.edwards.navy](https://forum.inductiveautomation.com/u/joshua.edwards.navy)\
**Post date:** [April 23, 2026, 5:33pm UTC](https://forum.inductiveautomation.com/t/trying-to-get-better-graph-performance/115219/1 "2026-04-23T17:33:31Z")

</div>

I am having an issue with loading data for some XY graphs. I have Ignition Cloud on an AWS t3.medium. It's connected to a Postgres db.t4g.micro. On the page that is having issues there are 11 XY graphs. My gateway is timing out after 10 seconds (I increased it troubleshooting this issue) when trying to get Tag History. I'm the only one using the page because it's still in development. This is a demo project. I haven't implemented the Realtime toggle and considering deleting it after the page is having trouble loading 11 graphs.

> **Page**
>
> ![Designer](https://us1.discourse-cdn.com/inductiveautomation/original/3X/b/2/b2bc7ef617c144d7c5f3111acc01e0a935d79ab0.png)
> 
> ![Page](https://us1.discourse-cdn.com/inductiveautomation/original/3X/0/0/00964c0af6fe96f2ccbd7746397eff0de69d4bc4.png)

As this is a demo, the data doesn't come from a PLC. I created a .NET app that runs on a laptop that connects to a local Ignition Gateway and changes tags at a rate of 500ms via a separate port on the gateway from the internet. This Gateway is connected to the AWS server and uses the AWS historian for these Demo tags. The app is designed so it only changes relevant tags to the simulation. I have changed the simulation rate to 1 sec and the store and forward rate is between 2 -4 datapoints/sec.

> **Store & Forward from Local Gateway**
>
> ![Local Gateway Store and Forward](https://us1.discourse-cdn.com/inductiveautomation/original/3X/b/7/b77e8e052454b7bede246ef231af9b79b625eaec.png)

The data bindings on the graphs is using Tag History Historical with starting date based on a datetimeinput and end date on another datetimeinput. They tag data path comes from a custom param.

> **Custom Param**
>
> ![Custom param binding](https://us1.discourse-cdn.com/inductiveautomation/original/3X/e/9/e9a92d9a87c076ee4ece36272b28a20abe6e76be.png)
> 
> ![data bind](https://us1.discourse-cdn.com/inductiveautomation/original/3X/1/1/11e6516ef1af1b914be718f8f0b1f1e37cb84f76.png)
> 
> ![Custom params](https://us1.discourse-cdn.com/inductiveautomation/original/3X/1/4/14f4906557f38eea8e5d11fc6ab965a5a058ce0e.png)

The Postgres database doesn't seem to be overwhelmed, but this is the first time I've ever investigated a database for performance issues.

> **Posgres Metrics**
>
> ![database load](https://us1.discourse-cdn.com/inductiveautomation/original/3X/b/4/b42f172e40e17cc1f46dd77faefcf2844295374e.png)
> 
> ![Database metric 2](https://us1.discourse-cdn.com/inductiveautomation/original/3X/f/e/fe932f31e6e6fa2bc031b6e477ccc500cd1d1363.png)
> 
> ![Database metric 1](https://us1.discourse-cdn.com/inductiveautomation/original/3X/d/8/d84ca96ff0d4bda64e466e2193930d8823e65b78.png)

Ideally I could perform the queries on the graphs as they become visible to reduce load, but I haven't found anything on pagination or loading as you scroll. What can I do to reduce the load of these graphs?

> **Error on Gateway**
>
> ![Ignition gateway error](https://us1.discourse-cdn.com/inductiveautomation/original/3X/b/3/b3aa6f3aff2cc724a91c5aef34d46d7647ec8907.png)

---

<div class="post-metadata">

**Author:** ![MMaynard](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/mmaynard/32/3366_2.png) [@MMaynard](https://forum.inductiveautomation.com/u/MMaynard)\
**Post date:** [April 23, 2026, 5:49pm UTC](https://forum.inductiveautomation.com/t/trying-to-get-better-graph-performance/115219/2 "2026-04-23T17:49:05Z")

</div>

Can you show the status of the database connections when you are running this?

Gateway Web page-status-databases-History DB-Details

What you are showing should not be timing out with any standard history query.

---

<div class="post-metadata">

**Author:** ![joshua.edwards.navy](https://avatars.discourse-cdn.com/v4/letter/j/b19c9b/32.png) [@joshua.edwards.navy](https://forum.inductiveautomation.com/u/joshua.edwards.navy)\
**Post date:** [April 23, 2026, 6:04pm UTC](https://forum.inductiveautomation.com/t/trying-to-get-better-graph-performance/115219/3 "2026-04-23T18:04:47Z")

</div>

Here's DB Connections page on the Cloud:

> **Cloud DB Connections**
>
> ![Cloud DB Connections](https://us1.discourse-cdn.com/inductiveautomation/original/3X/0/1/01b2fb13e2ece96015bfac556dbf15f3a6ebb043.png)

> **DB Details while a query ongoing**
>
> ![DB Details while query ongoing](https://us1.discourse-cdn.com/inductiveautomation/original/3X/a/d/ad616abb18916b863948bca73a15b4c247ccc79f.png)

I hope this is what you are looking for.

Edit:

> **Metric Dashboard on DB queries**
>
> ![Metric Dashboard - Queries](https://us1.discourse-cdn.com/inductiveautomation/original/3X/c/1/c1fde072f08b0286a2334329a6fcc6c14e2a37b5.png)

---

<div class="post-metadata">

**Author:** ![Nol](https://avatars.discourse-cdn.com/v4/letter/n/8e8cbc/32.png) [@Nol](https://forum.inductiveautomation.com/u/Nol)\
**Post date:** [April 23, 2026, 6:26pm UTC](https://forum.inductiveautomation.com/t/trying-to-get-better-graph-performance/115219/4 "2026-04-23T18:26:04Z")

</div>

I'd suggest minimizing the load first to see what that looks like and then work from there adding things back in. For example drop the number of points in the query on each graph to like 10 it to historical mode set to a 1 minute window. See if that loads to determine if it's just a loading issue or if its something else.

I'd also monitor your network traffic through task manager and see if you're seeing a spike. Once I ran into an issue where one chart was pulling 10-20mbps of load just because it had a lot of data points and was accidently set to real time mode.

---

<div class="post-metadata">

**Author:** ![joshua.edwards.navy](https://avatars.discourse-cdn.com/v4/letter/j/b19c9b/32.png) [@joshua.edwards.navy](https://forum.inductiveautomation.com/u/joshua.edwards.navy)\
**Post date:** [April 23, 2026, 6:44pm UTC](https://forum.inductiveautomation.com/t/trying-to-get-better-graph-performance/115219/5 "2026-04-23T18:44:28Z")

</div>

Here is some screenshots for network traffic.

> **Local Gateway (2 ports)**
>
> ![Local Gateway comms to internet](https://us1.discourse-cdn.com/inductiveautomation/original/3X/1/5/159c3ea4840ebde76448e52f38c6c2461f4d83ed.jpeg)
> 
> ![Local Gateway comms with sim](https://us1.discourse-cdn.com/inductiveautomation/original/3X/e/7/e73486622425a088d068308ccd1a356548692358.jpeg)

> **Cloud Gateway during query**
>
> ![Cloud RX TX during query](https://us1.discourse-cdn.com/inductiveautomation/original/3X/f/e/fe1be50c969ebfad68e9db104ad8c1388bb10c4f.png)

The max tx speed seems a little high. I tried it a couple times after this high spike and I couldn't get it to tx that fast again.

> **Follow up test**
>
> ![Cloud follow up RX TX during query](https://us1.discourse-cdn.com/inductiveautomation/original/3X/7/3/73b6cdaa3b0c920effb4ff0fef9e2feb87d7730a.png)

Edit 2: after some further testing I believe the high tx speed correlates to when a new session is started.

---

<div class="post-metadata">

**Author:** ![joshua.edwards.navy](https://avatars.discourse-cdn.com/v4/letter/j/b19c9b/32.png) [@joshua.edwards.navy](https://forum.inductiveautomation.com/u/joshua.edwards.navy)\
**Post date:** [April 23, 2026, 6:51pm UTC](https://forum.inductiveautomation.com/t/trying-to-get-better-graph-performance/115219/6 "2026-04-23T18:51:27Z")

</div>

Changed all graphs to only 10 points.

> **Page after changing all graphs to 10 points**
>
> ![Page after count changed to 10](https://us1.discourse-cdn.com/inductiveautomation/original/3X/b/6/b69f266928f8e757d0d5c74dacbeb494a268badb.png)

> **2nd error**
>
> ![2nd error](https://us1.discourse-cdn.com/inductiveautomation/original/3X/e/8/e8baa70da961ead2e26a3b49f93253f4160e5c6c.png)

Edit: could my custom param paths not be built and the graphs are sending out a Tag History request for null? Seems odd that it would do this and that a null request would cause a server error.

---

<div class="post-metadata">

**Author:** ![joshua.edwards.navy](https://avatars.discourse-cdn.com/v4/letter/j/b19c9b/32.png) [@joshua.edwards.navy](https://forum.inductiveautomation.com/u/joshua.edwards.navy)\
**Post date:** [April 23, 2026, 7:11pm UTC](https://forum.inductiveautomation.com/t/trying-to-get-better-graph-performance/115219/7 "2026-04-23T19:11:36Z")

</div>

Could it possibly be the tags on the local gateway?

> **Example Local Tag**
>
> ![Simulated Tag](https://us1.discourse-cdn.com/inductiveautomation/original/3X/f/8/f8fe483e7a68db15565fc72874dae11e11e1e162.png)

---

<div class="post-metadata">

**Author:** ![joshua.edwards.navy](https://avatars.discourse-cdn.com/v4/letter/j/b19c9b/32.png) [@joshua.edwards.navy](https://forum.inductiveautomation.com/u/joshua.edwards.navy)\
**Post date:** [April 24, 2026, 8:08pm UTC](https://forum.inductiveautomation.com/t/trying-to-get-better-graph-performance/115219/8 "2026-04-24T20:08:50Z")

</div>

I think I found my problem.

> **Problem**
>
> ```python
> def waitForFracWell(timeout=2.0, interval=0.05):
> start = time.time()
> while time.time() - start < timeout:
> wellNum = getFracWell(12)
> if wellNum != 0:
> return wellNum
> time.sleep(interval)
> return 0
> 
> def getFracWell(numWells):
> #print("numWells passed in: ", numWells)
> base = "[IPC Demo]Pad/Well"
> placeFrac = "/HMI/Modes/Frac"
> removeFrac = "/HMI/Modes/Remove Frac"
> balldrop = "/HMI/Modes/Balldrop Frac"
> 	
> paths = []
> 	
> for x in range(numWells):
> i = x + 1
> paths.append(base + str(i) + placeFrac)
> paths.append(base + str(i) + removeFrac)
> paths.append(base + str(i) + balldrop)
> 	
> results = system.tag.readBlocking(paths)
> 	
> for x in range(numWells):
> placeVal = results[x*3].value
> removeVal = results[x*3 + 1].value
> balldropVal= results[x*3 + 2].value
> 		
> if placeVal or removeVal or balldropVal:
> return x + 1
> 	
> return 0
> 
> ```

I'm wondering if these readBlocking are suspending processing for too long.

I tried to do the following, but tag.readAsync doesn't allow passing in parameters

> **Doesn't work**
>
> ```python
> def onTagChange(initialChange, newValue, previousValue, event, executionCount):
> if (
> not initialChange 
> and newValue is not None 
> and newValue.value != previousValue.value
> #and executionCount % 2 == 0 #filters out odd repeating onTagChange
> ):
> value = newValue.value
> tagPathStr = str(event.tagPath)
> tagName = tagPathStr.split("/")[-1]
> #print("New Value: ", newValue.value)
> #print("tagPath: ", tagPathStr)
> #test = system.tag.readBlocking(["[.]Zipper Entries/Frac Pin"], 1000)
> if isinstance(value, bool) and tagName.endswith("Pin Ok"):
> general.PinChange(tagName)
> 
> # in Project Library "general"
> 
> def PinChange(tagName):
> getFracWell(12, tagName)
> 
> def getFracWell(numWells, tagName):
> base = "[IPC Demo]Pad/Well"
> placeFrac = "/HMI/Modes/Frac"
> removeFrac = "/HMI/Modes/Remove Frac"
> balldrop = "/HMI/Modes/Balldrop Frac"
> 	
> paths = []
> 	
> for x in range(numWells):
> i = x + 1
> paths.append(base + str(i) + placeFrac)
> paths.append(base + str(i) + removeFrac)
> paths.append(base + str(i) + balldrop)
> 	
> system.tag.readAsync(paths, _callback(tagName, numWells))
> 
> def _callback(results, tagName, numWells):
> for x in range(numWells):
> placeVal = results[x*3].value
> removeVal = results[x*3 + 1].value
> balldropVal= results[x*3 + 2].value
> 		
> if placeVal or removeVal or balldropVal:
> _pinChange(x + 1, tagName)
> 
> def _pinChange(wellNum, tagName):
> if wellNum and wellNum != 0:
> wellNameTag = "[IPC Demo]Pad/Well" + str(wellNum) + "/Last Known Name"
> wellName = system.tag.readBlocking([wellNameTag])[0].value
> action = ""
> pin = 0
> FracName = ""
> VtName = ""
> WlName = ""
> WsmName = ""
> 		
> prefix = tagName.replace(" Pin Ok", "")
> 
> if (prefix == "Frac"):
> action = "Frac pin entered"
> pin = system.tag.readBlocking(["[IPC Demo]Zipper Pins/Frac Pin"])[0].value
> if pin != 0:
> FracName = findUserName(pin, "FRAC")	
> #print(pin)
> elif (prefix == "VT"):
> action = "Valvetech pin entered"
> pin = system.tag.readBlocking(["[IPC Demo]Zipper Pins/VT Pin"])[0].value
> if pin != 0:
> VtName = findUserName(pin, "VT")		
> elif (prefix == "Wline"):
> action = "Wireline pin entered"
> pin = system.tag.readBlocking(["[IPC Demo]Zipper Pins/Wline Pin"])[0].value
> if pin != 0:
> WlName = findUserName(pin, "WIRELINE")
> elif (prefix == "WSM"):
> action = "WSM pin entered"
> pin = system.tag.readBlocking(["[IPC Demo]Zipper Pins/WSM Pin"])[0].value
> 
> if pin != 0:
> WsmName = findUserName(pin, "WSM")
> else:
> print("Zipper Pin tag change didn't find any Pin Ok")
> 		
> if pin != 0:
> namedQuery = "Insert User Action"
> queryParams = {"wellNum": wellNum, "wellName": wellName, "action": action, "pin": pin, "frac": FracName, "wsm": WsmName, "wl": WlName, "vt": VtName, "wellPressure": "", "fracPressure": ""}
> system.db.execUpdate(namedQuery, queryParams)
> 
> ```

---

<div class="post-metadata">

**Author:** ![paul-griffith](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/paul-griffith/32/37249_2.png) [@paul-griffith](https://forum.inductiveautomation.com/u/paul-griffith)\
**Post date:** [April 24, 2026, 9:04pm UTC](https://forum.inductiveautomation.com/t/trying-to-get-better-graph-performance/115219/9 "2026-04-24T21:04:20Z")

</div>

You can use `lambda` to make a closure that captures args from the calling scope.  
As in:

```python
system.tag.readAsync(paths, lambda results: _callback(results, tagName, numWells))

```

---

<div class="post-metadata">

**Author:** ![joshua.edwards.navy](https://avatars.discourse-cdn.com/v4/letter/j/b19c9b/32.png) [@joshua.edwards.navy](https://forum.inductiveautomation.com/u/joshua.edwards.navy)\
**Post date:** [April 30, 2026, 8:29pm UTC](https://forum.inductiveautomation.com/t/trying-to-get-better-graph-performance/115219/10 "2026-04-30T20:29:21Z")

</div>

So I ended up finding my issue. Rookie MQTT mistake.

I found by using a direct tag bind to a tag that for the mqtt historian tag I had to use a different tag than the one listed in the mqtt engine. What lead me down this path was reading the mqtt docs and there were two different ways to setup the edge historian for tag data. One of them pointed out that the edge historian bypassed the tag change historian. This got me wondering if this resulted in an odd historian tag. Sure enough this was the case. I added a new Param to my view for this different path and passed it to all of my Graphs.
