Instances

Whereas a Model is the standard definition of something (asset, process, etc), an Instance is the actual thing. For example, a Model for a line may define a quality managers view of the line (scrap, good count, bad count). If there are 10 lines, there would be 10 instances, each populated with the data sources specific to the line.

Create an Instance

  1. Navigate to Instances in the configuration’s Main Menu. Here you can add, edit, and view instances. To add a instance, click the New Instance button.

  2. Enter a Name of the instance and the Model it’s based on. This will automatically pre-populate the attributes to be assigned to this instance. Optionally enter in a Description and a Group As folder to categorize the instance. Click Next to continue.

New Instance

  1. The Model attributes are shown in the tree. Use the tree and Detail and Outline tabs to configure each attribute. Use the References panel to find and select sources of interest and drag them directly on the expression or reference field, or into the tree. More information on attribute configuration is provided below. Click the Submit button when finished.

Attribute Configuration

The tree view shows the attributes for the parent model and all child models. Each attribute has the following settings.

Instance Attribute

Expression Type

This controls how the attribute is processed. The two options are Reference and Expression.

Reference

For simple cases, like mapping an attribute to an OPC UA tag value, use a Reference type. Reference types don’t require JavaScript to execute when reading the instance and are faster.

See References for more details.

Expression

Use the Expression type for attributes that require JavaScript. This could be for scaling a value, combining multiple values, or applying other logic. These attributes require the use of the JavaScript engine which has slight overhead. These attributes also require an explicit return statement.

Drag & drop references from the reference panel, and write JavaScript as needed. Hover over and click the expansion icon in the top right of the expression box or enter CTL-SHIFT-F while inside an expression to expand the expression view and provide more area for writing expression.

See Expressions for more details.

Expression Attribute

Reusing JavaScript Snippets

In some cases, there are snippets of JavaScript code that get reused in many expressions across many Instances.

In these situations Functions can be used to reduce duplicate code.

Default Value

The default value is used if the expression or reference field are empty or fail to compute a result. If there is no default value the default model attribute value is used.

Default values are represented as JSON. Simple number values can be entered as 123. String must be quoted. Complex objects like {“attribute”: 123} are also supported.

Attribute Hierarchy

Object and Modeled attribute types are shown as hierarchy in the tree. The root node can be set to Reference or Expression type. When reading the Instance, the root node is evaluated first. If it returns hierarchy the hierarchy is expanded into the child attributes by name using case sensitive matching. Child attributes can then override the value from the parent attribute. Below is an example.

Consider the following hierarchy in an instance, coming from an attribute of type Object or Modeled.

{
  "lineMotor" : {       // Mapped {{Instance.line1Motor}}
    "speed": "",        // left blank
    "location": "line1" // default value set to line1
  }
}

Assume {{Instance.line1Motor}} produces the following data when read.

{
  "speed": 100,
  "location": "test",
  "someOtherAttribute": "ignore"
}

When the parent instance is read, {{Instance.line1Motor}}.speed maps to the child attribute. {{Instance.line1Motor}}.location is overridden. The other attribute is ignored as it has no mapping. The result is as follows.

  "lineMotor" : {
    "speed": 100,
    "location": "line1"
  }

Parameters

Instance parameters provide a way to make generalized instances that can return different data when called. For example an Instance can represent a type of machine and a machineID parameter can be passed as a parameter to control what machine to read.

For more details on how to use parameters with instances, please see the Parameters section.

Instance Subscriptions

When an instance references one or more subscribable sources, you can subscribe directly to the instance using an Event Trigger. The subscription automatically monitors all underlying subscribable sources and generates an event whenever any of them change.

Subscription Behavior

  • The instance is built whenever one or more of its subscribed sources produce an event
  • If multiple subscribed sources update within the same batching window, the instance is built once rather than once per update. The batching window is dynamically sized based on system load, with a minimum of 100ms
  • If the same source provides two different updates within the same window, they will be processed individually to avoid dropping data
  • When the instance is built, non-subscribable sources (e.g., SQL inputs) are polled to retrieve their current values. As an optimization, polled sources are read once per batching window regardless of how many updates triggered that build, which improves throughput in most workloads
  • Before publishing, the resulting payload is compared to the previous output. Identical consecutive payloads are suppressed — no two back-to-back instance updates will be the same
  • The Output Mode configured on the Event Trigger controls whether the full payload or only the changed attributes are included in each update

Current Limitations:

  • There is no way to require that all subscribed sources produce an event before the instance is built. The instance builds as soon as any one subscribed source updates and the batching window completes.
  • Because polled sources are read once per batching window, high-frequency instances may not reflect every individual read of an indexed source. Because of this, use-cases revolving around input indexing are not recommended for instances that can fire at a high frequency.

Requirements:

  • The instance must contain at least one subscribable source
  • If the instance has no subscribable sources, subscription attempts will fail

Cached Inputs and Data Symmetry

Some input types, such as OPC UA Branches, OPC UA Collections, and Sparkplug B Inputs, maintain a local cache of previously received data. This cache is what drives the polled read experience, returning a complete accumulated state rather than just the latest delta.

When one of these inputs is referenced in an instance, subscription events reflect the full cached state to stay consistent with the polled read experience. This is different from subscribing to the input directly, where only the data from that specific update is delivered.

For example, consider an OPC UA Branch with the following structure:

- rootBranch
    - tag1  (value: 100)
    - tag2  (value: "2026-01-25T20:11:49+0000")
    - tag3  (value: 0.53)
    - tag4  (value: "open")

If tag1 changes to 150 and tag2 changes to “2026-01-25T20:11:51+0000”, the OPC UA server sends a subscription update containing only the changed tag:

// Direct input subscription event (only the changed tag)
{
  "rootBranch": {
    "tag1": 150,
    "tag2": "2026-01-25T20:11:51+0000"
  }
}

When the same branch is referenced as an instance attribute, the subscription event reflects the full cached state:

// Instance subscription event (full cached state)
{
  "rootBranch": {
    "tag1": 150,
    "tag2": 200,
    "tag3": 300
  }
}

This keeps instance outputs consistent whether they are triggered by a subscription or read by polling.

For more information on subscriptions and event-driven data flows, see Event Trigger.

Advanced

Initialization

This setting is only available when Legacy Execution Mode is disabled. The Initialization block is the first thing that executes when the instance is read. Use this to read common data sources that are required in the instance, or to initialize default values that are used in multiple attributes.

Example of an initialization block to read a source and set defaults values.

let mesData = {{Connection.mes.machineStatus({"machineid":"10"})}}
variables.machineName = mesData.name
variables.defaultSpeed = 100

These can then be referenced in Expression attributes as follows.

return (variables.machineName)

Templating

Instances can be templated to quickly create many Instances that have the same basic configuration.

See Templating for more details.

Expand Arrays

The Expand Arrays feature is useful in cases where the source data is an array of objects (e.g. SQL rows) and you want to transform each row through the model and output a transformed array. Below is an example of how to accomplish this.

Consider the source input {{Connection.sql.rows}}, which returns the following data.

[
  {
    "timestamp": 123,
    "value": 100
  },
  {
    "timestamp": 456,
    "value": 101
  }
]

Configure the Instance as follows, where the time and rpm attributes are mapped to index [0] of the array. Index [0] is important, because the Expand Array feature breaks the input array into N arrays of size 1 (i.e. index [0]) and runs each array through the Instance.

{
  // Note this format is provided as an example, and this configuration must be done through the UI using the reference panel
  "time": {{Connection.sql.row}}[0].timestamp,
  "rpm": {{Connection.sql.row}}[0].value,
  "model": "myModel"
}

The resulting Instance read looks as follows, with each row run through the Instance.

[
    {
      "time": 123,
      "rpm": 100,
      "model": "myModel"
    },
    {
      "time": 456,
      "rpm": 101,
      "model": "myModel"
    }
]

Note it’s possible to combine data from multiple arrays using this feature, but each source array must have the same number of rows.

Legacy Execution Mode

Controls how the instance is read. When enabled, Instance are read like they were in version 3.x and older. For new instance, leave this setting disabled.

In version 3.X and older, instance attributes were calculated using a unique JavaScript environment for each attribute. This approach isolated the execution of each attribute, but could significantly impact performance when an instance had a lot of attributes. Expressions also did not require return statements, making it confusing to understand what an expression returned when the expression included complex JavaScript code.

When this setting is disabled, the instance uses a single JavaScript context to execute all expressions, resulting in significant speed gains. Expression also must have return statements. For simple attributes use the Reference type, but any attribute set to an Expression type must include a return in the expression. When disabled, the Initialization block is also available.

Migrating Legacy Instances

To migrate a legacy instance a return statement must be added to the expression.

Additionally, model schema validation has been improved for new instances. It is recommended that a migrated instance is retested to ensure that the values produced do not cause an error with the new (more strict) schema validation.

The model validation for new instances is consistent with the Modeling and Model Validation stages in pipelines.

Instance Metadata in Expressions

Metadata about the Instance is available for use inside the Instance expressions. Below are examples of the available metadata and how to reference it.

Instance Metadata Description
instance.name() Returns the name of the instance. For templated instances this returns the templated name.
instance.model() Returns the model name of the instance.
instance.usage() Returns an array of usage paths for the instance. For example, if instance machine1 has a parent instance line, which is part of a plant/area hierarchy, than instance.usage()[0] returns the full path to the instance plant/area/line/machine1. The usage method takes an optional delimiter (ex. instance.usage("/")).