v2.1.3

anomalyco/opentuiv2.1.3Aug 4, 2026by phillipleblanc

AI Summary

A resource efficiency focused release introducing explicit CPU sizing controls, improved memory diagnostics, and fixes for Iceberg acceleration and federated outer join filters.

Key Highlights

  • New `runtime.cpu.cores` setting for explicit CPU targeting
  • More query memory available for Cayenne deployments
  • New gauges for memory usage and crash diagnostics
  • Fixed Iceberg acceleration for timestamptz columns
  • Restored WHERE filters on federated LEFT/RIGHT JOINs

New Features

  • CPU sizing configuration
  • Memory pool diagnostics (gauges)
  • Fixed Iceberg timestamptz acceleration
  • Federated outer join filter fix
  • Memory pool refusal error handling

Full Release Notes

Spice v2.1.3 is a patch release focused on resource efficiency: explicit CPU sizing with the new `runtime.cpu.cores` setting, more query memory for Cayenne deployments, and improved memory and crash diagnostics. It also fixes Cayenne acceleration of Iceberg datasets with `timestamptz` columns and restores `WHERE` filters on federated `LEFT`/`RIGHT JOIN` queries.

## What's New in v2.1.3

### CPU Sizing with `runtime.cpu.cores`

The new `runtime.cpu.cores` setting controls how many cores the runtime targets. Thread pools, query partitioning, and accelerator concurrency are all derived from it.

```yaml
runtime:
  cpu:
    cores: 4 # `auto` (default) detects. Accepts 4, 3.5, 3500m
```

Also available as `--cpu-cores` and `SPICE_CPU_CORES` (precedence: flag > environment > Spicepod).

This is most useful on large, shared nodes. A pod that sets `resources.requests.cpu` without a CPU limit exposes no cgroup quota, so the runtime sizes itself for every core on the node rather than its allocated share. Setting the entitlement aligns parallelism and memory footprint with the CPU the pod actually receives.

The effective value, its source, and the derived sizing are logged at startup and exported as the `spiced_cpu_budget_cores` gauge.

### More Query Memory for Cayenne Deployments

The [Cayenne](https://spiceai.org/docs/components/data-accelerators/cayenne) compaction memory pool is now reserved only for accelerations that can compact into it: file mode with a small-write refresh profile. Other deployments, including `refresh_mode: full`, keep the full memory limit available to queries — up to 6.4 GiB on a 32 GiB limit, with no configuration change.

Memory budgets are now derived from the process's own cgroup limit rather than total host memory.

### Diagnostics

Three new gauges report memory in use: `query_memory_pool_used_bytes`, `cayenne_compaction_memory_pool_used_bytes`, and `process_resident_memory_bytes`.

Memory pool refusals now return `ResourcesExhausted` and HTTP `503`, distinguishing them from query errors.

Fatal native signals (`SIGSEGV`, `SIGBUS`, `SIGILL`, `SIGFPE`) report the signal, faulting address, and thread before exit, so a crash can be diagnosed from logs.

Fixed a bug where setting `runtime.task_history.enabled: false` also disabled every query metric — `query_duration_ms`, `query_execution_duration_ms`, `query_executions`, `query_failures`, `query_returned_rows`, and `query_returned_bytes`. These are now reported regardless of the task history setting.

### Cayenne Acceleration of Iceberg `timestamptz` Columns

Accelerating an Iceberg dataset with a `timestamptz` column using the [Cayenne](https://spiceai.org/docs/components/data-accelerators/cayenne) engine previously failed during the refresh write with an error resolving the time zone `+00:00`. Iceberg maps every `timestamptz` column to the fixed-offset Arrow time zone `+00:00`, which the file writer could not resolve when building column statistics. Fixed-offset time zones (`±HH:MM`, `±HHMM`, and `±HH`) are now resolved wherever time zones are handled, so these datasets accelerate correctly.

### Federated Outer Join Filters

A federated query combining a `LEFT JOIN` with a `WHERE` filter on the left table previously returned all rows instead of the filtered rows: when the query was pushed down to the data source or accelerator, the filter was folded into the `JOIN ON` clause, where it no longer filters the left side (`RIGHT JOIN` was affected symmetrically). Filters now stay on the side of the join they came from, so these queries return the correct rows.

## Contributors

- [@lukekim](https://github.com/lukekim)
- [@sgrebnov](https://github.com/sgrebnov)
- [@phillipleblanc](https://github.com/phillipleblanc)
- [@bjchambers](https://github.com/bjchambers)
- [@Jeadie](https://github.com/Jeadie)

## Breaking Changes

No breaking changes.

## Cookbook Updates

No new cookbook recipes.

The [Spice Cookbook](https://spiceai.org/cookbook) includes more than 100 recipes to help you get started with Spice quickly and easily.

## Upgrading

To upgrade to v2.1.3, use one of the following methods:

**CLI**:

```console
spice upgrade
```

**Homebrew**:

```console
brew upgrade spiceai/spiceai/spice
```

**Docker**:

Pull the `spiceai/spiceai:2.1.3` image:

```console
docker pull spiceai/spiceai:2.1.3
```

For available tags, see [DockerHub](https://hub.docker.com/r/spiceai/spiceai/tags).

**Helm**:

```console
helm repo update
helm upgrade spiceai spiceai/spiceai --version 2.1.3
```

**AWS Marketplace**:

Spice is available in the [AWS Marketplace](https://aws.amazon.com/marketplace/pp/prodview-jmf6jskjvnq7i).

## What's Changed

### Changelog

- feat(runtime): size every CPU-derived pool from the CPU entitlement by [@bjchambers](https://github.com/bjchambers) in [#12276](https://github.com/spiceai/spiceai/pull/12276)
- fix(runtime): carve the Cayenne compaction memory pool only when a dataset can compact into it by [@sgrebnov](https://github.com/sgrebnov) in [#12326](https://github.com/spiceai/spiceai/pull/12326)
- fix(runtime): size memory budgets from the process's own cgroup limit by [@lukekim](https://github.com/lukekim) in [#12263](https://github.com/spiceai/spiceai/pull/12263)
- fix(telemetry): read the cgroup CPU quota along the whole cgroup path by [@sgrebnov](https://github.com/sgrebnov) in [#12300](https://github.com/spiceai/spiceai/pull/12300)
- feat(runtime): expose the memory numbers that explain an OOM as gauges by [@lukekim](https://github.com/lukekim) in [#12195](https://github.com/spiceai/spiceai/pull/12195)
- fix(runtime): report a memory-pool refusal as ResourcesExhausted and answer it with 503 by [@sgrebnov](https://github.com/sgrebnov) in [#12289](https://github.com/spiceai/spiceai/pull/12289)
- fix(cayenne): the write-concurrency raise must respect the memory brake by [@lukekim](https://github.com/lukekim) in [#12317](https://github.com/spiceai/spiceai/pull/12317)
- feat(spiced): report fatal signals before exit by [@sgrebnov](https://github.com/sgrebnov) in [#12334](https://github.com/spiceai/spiceai/pull/12334)
- fix: report query metrics when task history is disabled by [@sgrebnov](https://github.com/sgrebnov) in [#12227](https://github.com/spiceai/spiceai/pull/12227)
- chore(deps): repoint vortex at the 2.1 fixed-offset timezone fix by [@phillipleblanc](https://github.com/phillipleblanc) in [#12455](https://github.com/spiceai/spiceai/pull/12455)
- chore(deps): bump datafusion rev for outer-join unparser fix by [@Jeadie](https://github.com/Jeadie) in [#12460](https://github.com/spiceai/spiceai/pull/12460)

**Full Changelog**: <https://github.com/spiceai/spiceai/compare/v2.1.2...v2.1.3>