---
title: Measure processing latency in queries
sidebar_label: Measure Latency
---

You may want to calculate timestamps in the middle of a query to track when Deephaven processes changes and measure latency. This guide explains how to force a formula to re-evaluate every time a row changes, even when the formula has no input dependencies that changed.

## The problem: `now()` is not re-evaluated

Deephaven optimizes formula evaluation by only recomputing columns when their input dependencies change. This means a formula like `ProcessTime = now()` with no column dependencies will not be re-evaluated when existing rows are modified.

Consider this example:

```groovy
// ProcessTime is not re-evaluated when existing rows are modified
source = db.liveTable("MyNamespace", "MyTable").where("Date=today()")
result = source.update("ProcessTime = now()")
```

```python
# ProcessTime is not re-evaluated when existing rows are modified
source = db.live_table("MyNamespace", "MyTable").where("Date=today()")
result = source.update("ProcessTime = now()")
```

When rows in `source` are modified, the `ProcessTime` column retains its original value because `now()` has no column dependencies that trigger re-evaluation.

## Solution: Force formula re-evaluation with `SelectColumnFactory.ofAlwaysUpdate`

To force a formula to re-evaluate every time a row is modified, use `SelectColumnFactory.ofAlwaysUpdate`. This method creates a `SelectColumn` that bypasses the modified column set optimization and always re-evaluates when the engine sees a modification to the row.

```groovy
import com.illumon.iris.db.tables.select.SelectColumnFactory

source = db.liveTable("MyNamespace", "MyTable").where("Date=today()")

// ProcessTime will now update every time a row is modified
result = source.update(SelectColumnFactory.ofAlwaysUpdate("ProcessTime = now()"))
```

```python
import jpy

SelectColumnFactory = jpy.get_type(
    "com.illumon.iris.db.tables.select.SelectColumnFactory"
)

source = db.live_table("MyNamespace", "MyTable").where("Date=today()")

# ProcessTime will now update every time a row is modified
result_j = source.j_table.update(
    SelectColumnFactory.ofAlwaysUpdate("ProcessTime = now()")
)

from deephaven import Table

result = Table(j_table=result_j)
```

> [!NOTE]
> In Python, there is no native wrapper for `SelectColumnFactory.ofAlwaysUpdate`. Access the Java API via `jpy` interop as shown above.

## Calculate end-to-end latency

A common use case is calculating the latency between when data originated (e.g., a quote timestamp from an exchange) and when Deephaven processed it.

```groovy
import com.illumon.iris.db.tables.select.SelectColumnFactory

source = db.liveTable("MarketData", "Quotes").where("Date=today()")

// Add a column that captures when Deephaven processes each row modification
withProcessTime = source.update(SelectColumnFactory.ofAlwaysUpdate("ProcessTime = now()"))

// Calculate latency between the source timestamp and processing time
withLatency = withProcessTime.update(
    "LatencyNanos = ProcessTime - QuoteTime",
    "LatencyMs = nanosToMillis(LatencyNanos)"
)
```

```python
import jpy

SelectColumnFactory = jpy.get_type(
    "com.illumon.iris.db.tables.select.SelectColumnFactory"
)
from deephaven import Table

source = db.live_table("MarketData", "Quotes").where("Date=today()")

# Add a column that captures when Deephaven processes each row modification
with_process_time_j = source.j_table.update(
    SelectColumnFactory.ofAlwaysUpdate("ProcessTime = now()")
)
with_process_time = Table(j_table=with_process_time_j)

# Calculate latency between the source timestamp and processing time
with_latency = with_process_time.update(
    [
        "LatencyNanos = ProcessTime - QuoteTime",
        "LatencyMs = nanosToMillis(LatencyNanos)",
    ]
)
```

## How it works

When you use a regular formula like `ProcessTime = now()`, Deephaven tracks which columns the formula depends on. During an update cycle, the engine only re-evaluates formulas whose dependencies appear in the modified column set for that cycle.

`SelectColumnFactory.ofAlwaysUpdate` creates a `SelectColumn` with the `alwaysEvaluate` flag set to `true`. This tells the engine to always include this column in the re-evaluation set whenever the row is modified, regardless of whether the formula's dependencies changed.

## Performance considerations

- **Use sparingly**: The `ofAlwaysUpdate` mechanism bypasses an important optimization. Only use it when you genuinely need to capture the processing timestamp for every modification.
- **Combine operations**: If you need multiple always-evaluate columns, pass multiple `SelectColumn` instances to a single `update` call rather than chaining multiple updates.
- **Monitor impact**: Use the [Query Operation Performance Log](../sys-admin/internal-tables/query-operation-performance-log.md) to monitor the performance impact of your queries.

## Related documentation

- [Monitoring Queries](./monitor-queries.md)
- [Query Operation Performance Log](../sys-admin/internal-tables/query-operation-performance-log.md)
- [Update Performance Log](../sys-admin/internal-tables/update-performance-log-core.md)
- [SelectColumnFactory Javadoc](https://docs.deephaven.io/javadoc/2026.01/com/illumon/iris/db/tables/select/SelectColumnFactory.html)
