Skip to content

Styx v0.1.0 — one river, two banks

Choose a tag to compare

@arloliu arloliu released this 01 Aug 07:03
· 47 commits to main since this release
f96507d

Styx is a Go plugin framework for local, same-machine, process-isolated plugin communication: a shared-memory data plane (memfd descriptor rings, slab arena, eventfd wakeups) in place of gRPC-over-UDS, behind ordinary protobuf services and gRPC-style generated stubs.

Stability: pre-1.0 — the public Go API may still move between minor versions. The wire contracts (shm-abi.md, stream-protocol.md) are frozen and change only by explicit, versioned amendment.

Why "Styx"?

In the old maps of the underworld, the Styx is the river between two worlds — the boundary itself. That's a plugin framework: your host lives in one process, your plugin in another world entirely, with its own runtime and its own crash domain. When it dies, it dies over there. The boundary is the point — but a boundary you can't cross efficiently is just a wall, so everything depends on the ferry.

Styx is the ferry, and the fare is nearly nothing. Both banks touch the same water: a sealed shared-memory region — descriptor rings, a slab arena, eventfd wakeups — carries a unary round trip in ~2.4 µs where gRPC-over-UDS takes ~16. One fixed-size memfd, resident memory pay-as-you-touch. No daemons, no sidecars — one river, two banks.

The mythology holds up under load. The gods swore unbreakable oaths on the Styx — ours are the frozen shm-abi.md and stream-protocol.md. Achilles was dipped in it and came out nearly invulnerable — this transport was dipped in a chaos suite, a differential oracle, and a leak soak. And with state-preserving hot reload, Styx is the rare river you can cross back over: a plugin goes down, its state ferries home, its successor picks up where it left off.

Highlights

  • Shared-memory data plane — p50 2.4 µs unary round trip at a 64-byte payload, vs 7.7 µs over Unix domain sockets and 15.9 µs over gRPC-over-UDS. Faster than hashicorp/go-plugin in all 24 cells of the comparison matrix: 1.65×–4.72× on throughput, payloads 64 B–1 MiB, concurrency 1–64.
  • uds fallback + TransportAuto — same API, negotiated per plugin.
  • Protobuf IDL, gRPC-style stubs via protoc-gen-go-styx — unary and all three streaming shapes; callers never see shared-memory details.
  • Supervised lifecycle — crash isolation with restart policies, health from heartbeat progress counters, subscription-based supervisor events, and state-preserving hot reload.
  • Default arena geometry — a seven-rung ladder from 256 B to 1 MiB with headroom-aligned slabs, plus a worked sizing guide in docs/configuration.md.
  • Typed error surface — handler errors as *styx.Status, panic/crash isolation as typed errors, explicit retryability, and ErrOutcomeUnknown reserved for genuine ambiguity only.
  • Validated — differential suite against the UDS oracle, fault-injection (chaos) suite, long-running leak soak, and failpoint suite, all CI-gated.
  • Runnable examples — echo, streaming, hot-reload, a backpressuring slow handler, and a real consumer's device-plugin lifecycle contract (examples/device-gateway/).
  • Migrating from hashicorp/go-plugin? See docs/migration-from-go-plugin.md.

Docs

Design of record · Configuration · Plugin lifecycle · Supervisor events · Benchmarks · Performance headroom · CHANGELOG