Spice v2.3.1 (Sep 15, 2026)
Spice v2.3.1 is now available! π οΈ
Spice v2.3.1 is a patch release that improves performance of filtered Vortex scans, cache eviction, and query planning. It also improves installation reliability, subquery fallback, numeric conversion, and Cayenne writes.
Highlights in v2.3.1 include:
- Ordered Full Refreshes β Cayenne applies
sort_columnswhen a full refresh replaces a table - Faster Vortex Scans β selective filters read fewer bytes, and zones skip unrelated scan splits
- Faster
INLists β Vortex uses a set probe for large constant lists - Reusable Parameterized Plans β all parameter values use the same cached plan without sharing results
- Reliable Cache Eviction β declared keys and timestamp ties do not prevent eviction
- Installer and Container Reliability β the installer validates each archive, and scratch images provide a writable temporary directory
- Cayenne Memory-Mode DML β
DELETE,UPDATE, andINSERTis now supported when the acceleration uses the default in-memory mode
What's New in v2.3.1β
Cayenne Applies sort_columns During Full Refreshesβ
Cayenne previously applied sort_columns only during compaction. A dataset with refresh_mode: full replaces its table, so it did not run that compaction. Cayenne now sorts the replacement stream before it writes the refreshed table, and the ordered files let min/max statistics exclude unrelated files from selective queries.
In the reported TPC-H SF1 benchmark, point-lookup p50 latency improved by 16%, and the same query used 37% less CPU. The sort adds work to each full refresh, so only datasets that configure sort_columns pay this cost. See Full Refresh for full-refresh configuration.
Faster Vortex Scansβ
Vortex now waits for a pushed-down filter before it prepares projected column readers, so a split with no matching rows does not prepare those readers. Selective queries in the reported benchmarks read 45% to 58% fewer bytes, and bandwidth-constrained storage showed the largest latency improvements.
Vortex also checks each scan split against its zone statistics, and it returns an empty stream when the split cannot contain a matching row. In the reported TPC-H SF1 benchmark, point-lookup p50 latency improved by 12%, and CPU use per query fell by 53%. Nonselective scans do not use these shortcuts and remain unchanged within the reported run-to-run variation.
Large IN Lists Run Fasterβ
Vortex previously evaluated a constant IN list once for every row and every list item, so runtime grew with both dimensions. Vortex now builds a set once and probes it in one pass, and it uses value intervals to reject files before a scan.
A 32,768-value list over 1,048,576 rows fell from 44.57 seconds to 225 milliseconds in the reported benchmark. Small lists keep their existing evaluation path.
Parameterized Queries Reuse Logical Plansβ
The logical-plan cache previously included each bound parameter value in its key, so each value tuple created another entry for the same SQL text. The cache now stores an unbound plan for each SQL statement, and Spice binds the current values after it reads the plan. The SQL results cache still includes parameter values in its keys, so a result only matches a query with the same values.
The reported point-lookup benchmark improved p50 latency by 12.4% and p99 latency by 31.7%, and parameterized traffic creates fewer duplicate entries. Indexed primary-key lookups now report an exact row count to the query planner, so DataFusion can avoid an unnecessary repartition for a single-row probe.
Caching Accelerations Evict Reliablyβ
A refresh_mode: caching dataset can use size and row-count limits, and two defects could let the cache exceed these limits. A declared primary_key could expand the eviction key to the entire stored row, and an index marked as unique had the same fault. A Map column in the expanded key then made every sweep fail. Spice now keeps the group key limited to the request columns, and a refreshed entry also removes rows that disappeared from its latest response.
Many responses can share the same one-second fetch timestamp. The previous eviction predicate could then remove only 512 entries when this tie crossed the survivor boundary. The eviction sweep now combines a timestamp range with named boundary entries. The range removes the older bulk, so eviction converges under sustained ingestion.
Federation and Runtime Improvementsβ
- DuckDB and SQLite accelerations now handle more subqueries with
on_zero_results: use_source. This includes mixed fallback policies andANYorALLcomparisons. - Decimal-to-float casts now preserve the expected rounded value after a federated aggregate. For example, a PostgreSQL average of
47.5returns47.5. - Cayenne uses asynchronous filesystem calls from its asynchronous code. A slow data directory does not block the Tokio runtime at these call sites.
Installer and Container Reliabilityβ
The runtime installer now retries unsuccessful HTTP responses and invalid archives, and it accepts an archive only when it contains a regular spiced executable. The installer sends a configured token to GitHub release requests, and it does not send that token to runtime download hosts. On native Windows, spice upgrade now rejects the unsupported runtime upgrade instead of continuing with a partial upgrade.
The scratch-based standard and release images now provide a writable temporary directory at /app/tmp, which supports operations such as acceleration snapshot uploads.
Cayenne Memory-Mode DML Works as Expectedβ
A Cayenne acceleration uses mode: memory by default. Before this release, filtered DML statements did not change its in-memory rows as requested.
- A filtered
DELETEreported zero affected rows and left each matching row in place. - An
UPDATEcould create a duplicate live row for the same primary key. - An
INSERTover an existing primary key could keep both versions of the row.
DELETE, UPDATE, and INSERT now update the in-memory tier. The append path also enforces each declared primary_key according to its on_conflict setting. The SQL DML reference lists the supported statements.
Dependency Updatesβ
No dependency changes its version in this release. DataFusion remains at v54.1.0, Arrow remains at v58.3.0, and Vortex remains at v0.79.0. Spice updates the Arrow and DataFusion fork revisions for the Decimal-to-Float rounding fix and the scan improvements described above.
Contributorsβ
Breaking Changesβ
No breaking changes.
Cookbook Updatesβ
No new cookbook recipes.
The Spice Cookbook includes more than 104 recipes to help you get started with Spice quickly and easily.
Upgradingβ
To upgrade to v2.3.1, use one of the following methods:
CLI:
spice upgrade
Homebrew:
brew upgrade spiceai/spiceai/spice
Docker:
Pull the spiceai/spiceai:2.3.1 image:
docker pull spiceai/spiceai:2.3.1
For available tags, see DockerHub.
Helm:
helm repo update
helm upgrade spiceai spiceai/spiceai --version 2.3.1
AWS Marketplace:
Spice is available in the AWS Marketplace.
What's Changedβ
Changelogβ
- fix(arrow): report an exact row count from the indexed point-lookup scan by @krinart in #13972
- fix(caching): keep a declared key from disabling eviction and stranding stale rows (fixes #13976) by @bjchambers in #13992
- fix(deps): bump arrow-rs to correctly-rounded DecimalβFloat cast (closes #13978) by @Jeadie in #14012
- fix(caching): partition doomed entries at the survivor cutoff so eviction converges (closes #13994) by @Jeadie in #14021
- Fix subqueries with use_source acceleration by @phillipleblanc in #14022
- fix: restore OSS installer, CLI and test workflow coverage by @phillipleblanc in #14025
- perf(vortex): defer projection setup on filtered scans until the filter resolves by @bjchambers in #14035
- fix(cayenne): make DELETE, UPDATE and INSERT work on a
mode: memoryacceleration (fixes #12008) by @bjchambers in #14047 - fix(deps): bump arrow-rs fork pin for Decimal->Float rounding fix by @Jeadie in #14049
- perf(vortex): answer a constant IN list by probing a set, and falsify it by interval by @bjchambers in #14061
- fix(cayenne): apply
sort_columnswithrefresh_mode: fullby @peasee in #14063 - perf(vortex): skip a scan split whose zones cannot satisfy the filter by @peasee in #14064
- perf(cache): key the logical-plan cache on SQL text, not parameter values by @bjchambers in #14069
- fix(cayenne): move accelerator filesystem I/O off Tokio workers by @lukekim in #14073
- fix: Provide temporary directory in docker images by @Jeadie in #14089
Full Changelog: https://github.com/spiceai/spiceai/compare/v2.3.0...v2.3.1

