---
title: "Dynoxide 1.5.0 release notes - Martin Hicks"
description: "Dynoxide 1.5.0 charges vector reads the way DynamoDB now does, gives stream records unique eventIDs and DynamoDB-length sequence numbers, and matches SearchVectors errors. The full list, and what to check before upgrading."
canonical: https://martinhicks.dev/articles/dynoxide-150-release-notes
last-updated: 2026-10-23
---

![The Dynoxide hexagonal logo centred on a near-black background](https://martinhicks.dev/images/articles/dynoxide-0120-release-notes.png)23rd October 2026

# Dynoxide 1.5.0 release notes

[Dynoxide](https://dynoxide.dev) 1.5.0 is out, two days after [1.4.0](https://martinhicks.dev/articles/dynoxide-140-release-notes). The vector fixes came out of Parity Suite, and I wrote up the [billing change](https://martinhicks.dev/articles/dynamodb-vector-read-billing) earlier today, so this one's just the list.

The crate moves to `dynoxide-rs` 3.2.0. Everything else you install is 1.5.0.

## Behaviour changes

-   **A read of a table with a vector index is charged on the billed size.** DynamoDB now bills a vector at 4 bytes per dimension on reads as well as writes, so an item whose numbers take it over a 4KB boundary costs a unit less. That covers `GetItem`, `BatchGetItem`, `TransactGetItems`, `Query`, `Scan` and PartiQL reads. A read from a secondary index and the 400KB item limit still use the stored size ([#264](https://github.com/nubo-db/dynoxide/issues/264)).
-   **`GetItem` and `TransactGetItems` charge for the whole item**, whatever the projection returns, as `BatchGetItem` and DynamoDB already did.
-   **Stream `SequenceNumber`s are 21 digits**, within DynamoDB's range of 21 to 40. Records already in a database file show in the same form.
-   **`GetShardIterator` validates `SequenceNumber`.** `AT_SEQUENCE_NUMBER` and `AFTER_SEQUENCE_NUMBER` refuse a missing, wrong-length or unknown number with a `ValidationException`, where they used to read from the start. `TRIM_HORIZON` and `LATEST` refuse one rather than ignoring it.
-   **An import with `record_streams` records a `MODIFY`** with the old image when it overwrites a key, as `PutItem` does. It used to record an `INSERT` ([#265](https://github.com/nubo-db/dynoxide/issues/265)).
-   **`http-server` and `mcp-server` no longer turn on `cli`.** A library embedding the HTTP server with `native-sqlite` compiles 22 fewer crates. If you build the binary from an explicit feature list, add `cli`. If you relied on Dynoxide to enable `tracing-subscriber`'s `env-filter`, enable it yourself.

## Fixed

-   **A stream record's `eventID` is globally unique.** It was the sequence number, so an in-memory server issued `1`, `2`, `3` again after every restart, and a consumer that skips eventIDs it has seen dropped new events. New records get a random 32-character hex ID, stored with the record so every read returns the same one. Existing records keep theirs ([#258](https://github.com/nubo-db/dynoxide/issues/258)).
-   **Imported stream records** go to the shard `DescribeStream` lists and follow the table's `StreamViewType` ([#260](https://github.com/nubo-db/dynoxide/issues/260)).
-   **`SearchVectors` errors match DynamoDB's search endpoint** for null members, null or empty values, wrong and unknown types, and the order things are checked in ([#263](https://github.com/nubo-db/dynoxide/issues/263), [#266](https://github.com/nubo-db/dynoxide/issues/266), [#267](https://github.com/nubo-db/dynoxide/issues/267)).

## Security

-   **`tokio` 1.54.1** for RUSTSEC-2026-0386, a possible use-after-free in `AsyncFd`. Dynoxide doesn't use `AsyncFd`, but tokio is built into the binary and the server features, so the fix goes out with this release.
-   **`ctutils` 0.4.5** for RUSTSEC-2026-0385. It only reaches Dynoxide through a test dependency, so nothing shipped was affected.

## Before upgrading

-   **Short sequence numbers from earlier builds fail validation**, so a stream consumer holding one has to restart from `TRIM_HORIZON`.
-   **Downgrading replays the stream.** A sequence number saved under 1.5.0 doesn't resolve on an earlier release, and records written under 1.5.0 report different eventIDs there, so anything de-duplicating on eventID processes them again.
-   **`dynoxide-rs = "3.2"`** picks up the crate. For an npm project, `npm install --save-dev dynoxide@1.5.0` pins this release.

The [1.5.0 release notes](https://github.com/nubo-db/dynoxide/releases/tag/v1.5.0) have everything else.

## Further reading

-    [DynamoDB changed how it bills a vector read
    
    A DynamoDB read of an item with a vector attribute cost 2 read units on 9th October 2026 and 1 on 22nd October. What changed, what didn't, and what I can't explain.](https://martinhicks.dev/articles/dynamodb-vector-read-billing)
-    [Dynoxide 1.4.0: clean shutdowns and JSON Lines import
    
    Dynoxide 1.4.0 adds JSON Lines import, a clean way to stop an embedded server, and closer DynamoDB behaviour for updates and scans. What changed and what to check before upgrading.](https://martinhicks.dev/articles/dynoxide-140-release-notes)
-    [Running DynamoDB vector search locally
    
    Dynoxide runs DynamoDB vector indexes and SearchVectors on your own machine. What I measured about the index lifecycle before building it, where it will never match AWS, and how a validation-error rollout I caught in June finally ended.](https://martinhicks.dev/articles/running-dynamodb-vector-search-locally)

---

Source: https://martinhicks.dev/articles/dynoxide-150-release-notes
