# Xo 0.24 release notes


## Introduction

Xo 0.24 makes native Maps and Sets a hybrid persistent map, which takes a
mixed CRUD server at 1024 connections from 18.0k to 83.0k requests per
second. Native code generation is level with LLVM on arm64 and about 6
percent behind on amd64, builds are faster, and the standard library
gains XML, big numbers, compression, and a streaming JSON decoder.

## Changes to the language

- Moves of the move-only builders are flow sensitive: a `return`,
  `break`, `continue`, or failing `?` ends its path's moves, so a value
  moved there is still usable after the branch
  ([decision 0300](https://github.com/xo-lang/xo/blob/main/knowledgebase/decisions/0300-flow-sensitive-moves.md)).
- `embed` puts files in the binary
  ([decision 0304](https://github.com/xo-lang/xo/blob/main/knowledgebase/decisions/0304-embed-files.md)).
- A program's own values convert to the capability interfaces (`Fs`,
  `Proc`, `Env`, `Net`) on the native backends
  ([decision 0307](https://github.com/xo-lang/xo/blob/main/knowledgebase/decisions/0307-user-fs-native.md)).
- Wire names per format for JSON, SQL, and XML, and `derive Xml`
  ([decision 0315](https://github.com/xo-lang/xo/blob/main/knowledgebase/decisions/0315-derive-xml.md)).
- Prelude additions.

## Compiler and runtime

- Native Maps and Sets are the hybrid persistent map by default; the
  micro benchmarks stay within 1.2 times the lists
  ([decision 0291](https://github.com/xo-lang/xo/blob/main/knowledgebase/decisions/0291-native-map-log-and-fork.md)).
- Preemption polls on amd64 and on LLVM's x86-64 code, with the
  thread-local table no longer reused across a poll
  ([decision 0286](https://github.com/xo-lang/xo/blob/main/knowledgebase/decisions/0286-scheduler-stealing-preemption.md)).
- Native code generation level with LLVM on arm64 and about 6 percent
  behind on amd64
  ([the comparison](https://github.com/xo-lang/xo/blob/main/bench/results/compare-2026-10-21.md)).
- Faster builds: std interface hashing from tokens, per-file LLVM test
  splits, a run cache for std module tests, and reference counting
  insertion in about half its cold time.
- The Go backend compiles `path` and `uuid` from their Xo source and
  supports tuples of up to 64 elements
  ([decision 0312](https://github.com/xo-lang/xo/blob/main/knowledgebase/decisions/0312-std-written-once-go-backend.md)).

## Standard library

- `std/xml`
  ([decision 0314](https://github.com/xo-lang/xo/blob/main/knowledgebase/decisions/0314-std-xml.md)).
- `std/big`, with Karatsuba multiplication and recursive division
  ([decision 0311](https://github.com/xo-lang/xo/blob/main/knowledgebase/decisions/0311-std-big.md)).
- JSON `omitempty` and a streaming decoder
  ([decision 0309](https://github.com/xo-lang/xo/blob/main/knowledgebase/decisions/0309-json-omitempty-and-stream.md)).
- `std/compress` and gzip responses; `client_ip`.
- The HTTP/1.1 client keeps connections alive
  ([decision 0303](https://github.com/xo-lang/xo/blob/main/knowledgebase/decisions/0303-http1-client-keepalive-pool.md)).

## Tools

- `xo def`, `refs`, `rename`, and `symbols` cover runtime names, fields,
  variants, and interface methods.
- The strict inliner verifier runs in `xo dev goldens` and codegen
  checks.
- Every Go test names the `xo` it runs and refuses a stale one.
- `--no-preempt`; `xo build --profile`.
- Backend cache pruning fixed (an overflow, concurrent accounting, a
  prune version guard).

## Fixes

- CI and fresh builds work again: 0.23.0 cannot build them, because its
  inliner verifier rejects `main`.

