Xo is experimental. The source is now public on GitHub, or try Xo in your browser.

Xo 0.23 release notes

released 2026-10-20 · tag v0.23.0 · all releases

Introduction

Xo 0.23 makes Xo’s own backend the default on x86-64 hosts, keeps build caches across compiler rebuilds and shares them across programs, runs --race on arm64 with no clang, cuts HTTP tail latency under CPU-bound handlers from about 86 ms to about 3 ms at p99, and adds the first batch of a standard library modeled on Go’s.

Changes to the language

  • Field wire names, field as "key": T, and case rules for derived encodings (decision 0277).
  • A newtype encodes to JSON as its underlying value on every backend (decision 0097).
  • An interface value holding a handle or a function equals nothing.
  • ServerConn for accepted connections (decision 0280).

Tools

  • --race on the arm64 backend: Xo’s own linker loads a TSan runtime shipped with Xo, so no clang is needed (decision 0273).
  • One name resolver behind xo def, refs, doc, symbols and query, covering std too, with text output at a terminal; xo vet runs on std (decision 0289).
  • x86-64 native binaries carry DWARF line tables and variables on Linux and macOS. XO_TRACEBACK=locals shows the faulting frame’s values and inlined callees’ variables.

Compiler

  • Native is the default backend on x86-64 hosts too (macOS, Linux and Windows): xo build uses Xo’s own x86-64 backend, with no C toolchain, and --backend=llvm still selects LLVM (decision 0270).
  • Build caches are keyed by the code generation sources instead of xo’s binary, so a rebuilt xo keeps them: rebuilding xo after a driver-only change takes about 41% of a cold build (decision 0275). Standard library function bodies are shared across programs (decision 0271).
  • x86-64: immediates, load sinking and branch on compare (RSA signing 6% fewer instructions, other compute 2 to 8%).

Runtime

  • A parked root task hands its next task to an idle worker, so an accept loop is no longer stuck behind a running handler. With 8 CPU-bound handlers on Linux arm64, p99 from dial to response went from 86 ms to 2.4 to 3.1 ms (Go: 7.5 to 12.5 ms) (decision 0286).

Standard library

The standard library now follows Go’s for scope, code and tests, with Xo’s own API (decision 0276). New in this version:

  • std/url, base64, base32, binary encodings, and hashes with HMAC (decision 0279).
  • MIME, multipart, UUID and mail (decision 0282).
  • Public key signatures and keys (decision 0285).
  • Number parsing in any base, Go’s math results bit for bit on every backend, and std/netip (decision 0287).
  • A TLS client on an existing connection (decision 0281).
  • The std/sql driver interface.
  • A change log per module in std/changes.