Open Exchange v0.3.0-beta: the release where we tried to break it
Open Exchange just reached beta. Version 0.3.0-beta is tagged across all four repositories, and it's the first release we'd describe as something you can seriously build against.
Alpha was about making the engine fast. Beta was about making it trustworthy. For five weeks we worked through one theme: what happens when things go wrong, and can we prove the answer is "nothing bad".
The test that earns the word "beta"
The centerpiece of this release isn't a feature. It's a test that now runs on every single commit:
- Boot a real 3-node matching cluster, the OMS, PostgreSQL, and Redis on a clean machine.
- Send a stream of crossing orders.
kill -9the cluster leader. Mid-load, no warning.- Keep sending orders straight through the election.
- Restart the dead node, let it rejoin, and drain everything.
Then it checks the books. Every order in a terminal state. Every fill quantity exactly equal to the sum of its trade executions. Every trade with exactly one buyer and one seller at the same price and quantity. Every balance correct to the last unit, with zero stuck holds.
The first time we ran it honestly, it found three real bugs, including one that silently lost ledger rows when an order filled instantly. That's the point. A failover story you haven't tested is a failover story you don't have.
Money math you can't get wrong
Every money value now crosses the wire as an exact decimal string ("110224.00000000", never a floating-point number), and every multiplication inside the engine is exact or loudly rejected. An order too large to compute safely is refused up front with an OVERFLOW reject instead of being quietly truncated somewhere downstream.
Big ids are strings too, because JavaScript silently rounds 64-bit integers and we'd rather delete that entire bug class than document it.
A frozen contract
The v1 API (REST, gRPC, and the order WebSocket) is now frozen. Breaking changes require a new major version and a deprecation window. There's a documented error taxonomy, restart-surviving idempotency keys, and a published OpenAPI spec. If you build against v0.3.x, minor releases won't break you.
Secure by default
An unconfigured OMS now rejects every request instead of accepting them: authentication defaults to API keys, with JWT support and a pluggable provider interface for your own identity system. The admin API binds to loopback unless you explicitly configure a token. CORS is a deny-by-default allowlist. Secrets can come from files instead of environment variables. And every repo now runs dependency and secret scanning in CI.
The honest numbers
The performance baseline was re-measured with the new external media driver transport: 800,000 orders per second at 100.00% acceptance, with 0.22 µs median ingress latency, on a single desktop CPU running full 3-node Raft consensus.
Two qualifiers, because we publish those: that latency number is cluster admission, not end-to-end (end-to-end is dominated by a deliberate 20 ms egress batch we can tune), and the machine was a tuned i7-13700K, not a server. The full methodology, the raw data, and where the system bends past 800k are all in the repo.
What beta doesn't mean
No external security audit has happened yet. That's the biggest single item between here and anything that holds real funds, and we'd rather say it plainly than let a version number imply it. Open Exchange remains infrastructure: KYC, custody, fiat rails, and licenses are still yours.
Try it
The quick start goes from a fresh clone to a running exchange on one Linux box in a few minutes. The release notes have the full changelog, per repo. If you build something on it, or try to break it, we want to hear either way.