---
title: Replay a table programmatically
sidebar_label: Replay a table programmatically
---

`ReplayAccess` is a [type-specific table access](./table-access.md) that replays a static table from `db` as a refreshing
table based on a simulated clock. It's a lighter-weight, programmatic alternative to a [Replay Query](./replayer.md): a
Replay Query replaces an entire Persistent Query's `db.liveTable` calls with replayed data, whereas `ReplayAccess`
replays just the table you ask for, without needing a dedicated Persistent Query.

`ReplayAccess` is obtained via [`db.as`](./table-access.md):

```groovy
import io.deephaven.enterprise.database.ReplayAccess
import java.time.Instant

// replay data from the Date partition "2024-01-01", starting at timestamp '2024-01-01T15:00:00Z'
replayData = db
    .as(ReplayAccess.factory())
    .table("MyNamespace", "MyTableName", Instant.parse("2024-01-01T15:00:00Z"))
    .where("Date=`2024-01-01`")
```

By default, this:

- Infers the timestamp column from the table's schema — it must have exactly one `Instant` column.
- Replays relative to the system clock.
- Replays in unsorted mode (see [Sorted vs. unsorted replay](#sorted-vs-unsorted-replay) below).
- Produces an add-only output table.

Pass a `timestampColumnName` explicitly if the schema has more than one timestamp-typed column:

```groovy
replayData = db
    .as(ReplayAccess.factory())
    .table("MyNamespace", "MyTableName", Instant.parse("2024-01-01T15:00:00Z"), "TradeTime")
    .where("Date=`2024-01-01`")
```

## Advanced options

For more control — a custom `Clock`, a different `Source`, sorted replay, or blink/static output — build
`ReplayAccess.Options` directly with `Options.of(clock, source, mode, timestampColumnName, outputAttributes)`.

### Source

- `Source.historical(schema)` — replay from `db.historicalTable`.
- `Source.live(schema)` — replay from `db.liveTable` (fetched with `TableOptions.isRefreshing()` as `false`).
- `Source.tableAccess(factory, options)` — replay from another `db.as(...)` accessor, such as `IcebergTableAccess`. The table must be static. If a non-static table is provided, an exception will be thrown.

### Sorted vs. unsorted replay

- `ReplayMode.unsorted()` — replays the data, preserving the source's original order between rows.
- `ReplayMode.sorted()` — replays the data, sorted by timestamp.

As a simplified example, if the source table contains "timestamps" `[1, 5, 3]` (where each element in the list is a row),
a replay might proceed as follows:

| Simulated timestamp | Unsorted    | Sorted      |
| ------------------- | ----------- | ----------- |
| 0                   | `[]`        | `[]`        |
| 2                   | `[1]`       | `[1]`       |
| 4                   | `[1, 3]`    | `[1, 3]`    |
| 6                   | `[1, 5, 3]` | `[1, 3, 5]` |

### Output attributes

- `OutputAttributes.addOnly()` — refreshing, add-only output (the default used by the `table(namespace, tableName, startInstant[, timestampColumnName])` convenience overloads).
- `OutputAttributes.blink()` — refreshing, blink-table output.
- `OutputAttributes.staticOutput()` — non-refreshing output containing only the rows released so far, evaluated at the time it is requested.

## Related documentation

- [Type-specific table access](./table-access.md)
- [Create a replay query](./replayer.md)
- [Iceberg](../data-guide/batch-data/iceberg.md)
- [`ReplayAccess` Javadoc](https://docs.deephaven.io/javadoc/coreplus/2026.01/io/deephaven/enterprise/database/ReplayAccess.html)
