Build1 distinct publisher3 min readUpdated
A five-phase build order for a BEAM triangular arbitrage engine treats broadcast fan-out as the first bottleneck and JSON parsing as the third. The sequencing is the transferable part.
The Engineer · Build desk
Compiled by The EngineerSomething wrong?How this is made
A roadmap published on dev.to lays out a five-phase build order for a cryptocurrency triangular arbitrage engine in Elixir and Rust: a notification-oriented engine with an adjacency registry, then decoupled telemetry and a terminal dashboard, then a Rustler JSON parser NIF, then a config compiler hot-swap, then HMAC authentication for private API calls [1][2]. What makes it worth reading is the ordering: the first thing it attacks is message fan-out, and the Rust parser waits until phase three [2][3].
Phase one is structural. At boot the engine queries Binance's public /api/v3/exchangeInfo endpoint and runs a depth-first search for closed three-leg cycles that start and end at designated hub assets: USDT, BTC, ETH and BNB [4]. The stated objective is a sparse market adjacency matrix that routes updates point-to-point instead of using global broadcasts or sweeping iterations [3]. Latest bid/ask book data lives in a public ETS table named :tickers created with read_concurrency: true [5]. Two filters sit in front of the work. If an incoming update's bid, ask and quantities match what is already in ETS, execution aborts at the entry point, which the author calls a blocked flicker [6]. If the state did change, the row is written with a monotonic nanosecond timestamp and Registry.dispatch sends {:ticker_changed, symbol} only to the processes registered on that symbol [7]. Rule processes each register to the three symbols in their own triangle using Elixir's :duplicate Registry [8]. The consequence is that a tick's dispatch cost tracks the number of rules that contain that symbol, not the number of rules in the system [9]. Inside the rule, handle_info drains any further queued notifications before evaluating, so a burst of pending messages collapses into a single evaluation [10][11].
Phase two removes observability from the hot path. The roadmap treats IO.puts as a millisecond-level blockage and requires the rule engines to stay silent during evaluation [12]. Results go out through :telemetry to a stateless handler, which issues a non-blocking GenServer.cast to a separate metrics process [13]. That dashboard process keeps counters in memory and redraws on a Process.send_after loop every 200ms, or 5Hz [14], which caps terminal writes at five per second no matter how fast the ticker stream arrives [15].
Only then does the Rust NIF appear [2]. That sequence is defensible on its own terms: a faster parser sitting upstream of a broadcast fan-out delivers the same storm earlier, and per-message parsing wins get multiplied by whatever the fan-out factor is. Fixing the multiplier before the multiplicand is the cheaper order of operations, and it is also the order that keeps the risky part, native code inside the VM, until after the message topology is stable.
Two things to watch. The supplied roadmap text contains no latency measurements for any phase, while the headline asserts sub-microsecond performance, so the claim is unbenchmarked as published [16][17]. And phase four is labelled a "0ns config compiler hot-swap" [18] - zero nanoseconds is a description of compile-time inlining, not a measured figure, and it is the phase most likely to hide a cost. Note also that authentication for private API calls is phase five [2], which means everything before it is a read-only simulator.
Follow any of these and your For You feed starts watching them — no settings page required.
Ranked by verification strength, evidence, and original report placement.
Rule processes emit execution results with the :telemetry library; a stateless handler captures the events and issues a non-blocking GenServer.cast/2 to a dedicated satellite metrics (TUI) process, which the author says returns in nanoseconds and never blocks rule evaluation.
A dev.to roadmap describes a step-by-step engineering plan for an ultra-low latency cryptocurrency HFT triangular arbitrage engine using Elixir, Rust and the Notification-Oriented Paradigm (PON).
The development process is structured into five successive optimization phases in this order: Phase 1 PON Engine and Adjacency Registry; Phase 2 Decoupled Telemetry and TUI; Phase 3 Rustler JSON Parser NIF; Phase 4 0ns Config Compiler Hot-Swap; Phase 5 Private API HMAC Authentication.
The primary objective is to build a sparse market adjacency matrix that routes updates point-to-point, avoiding costly global broadcasts or sweeping iterations.
At boot the engine queries Binance's public /api/v3/exchangeInfo REST endpoint and runs a depth-first search to identify closed 3-leg arbitrage cycles starting and ending at designated hub assets USDT, BTC, ETH and BNB.
A public ETS table named :tickers is initialized with read_concurrency: true and stores the latest bid/ask order book data.
Evidence-backed comparisons of source perspectives and observed adoption signals. Read the methodology
Which Builder, Operator, and Investor concerns the observed source mix emphasized—not a truth score.
Evidence, demonstrated adoption, hype gap, incentives, and confidence are assessed independently, each on its own current evidence. How these are measured.
Readable code, no measurements
The cluster rests on one self-published article. Its architectural claims are directly inspectable — the ETS creation flags, the Registry.dispatch closure, the drain_notifications receive/after 0 pattern and the 200ms redraw timer all appear as code, which is real evidence about mechanism. Nothing in the supplied text evidences performance: there is no harness, sample size, percentile, hardware note or end-to-end timing, and the one numeric figure (12,000ns to under 600ns parsing) is asserted rather than demonstrated. Mechanism evidence is decent; the sub-microsecond premise is unevidenced.
No adoption signal in sources
The supplied material contains no release, deployment, package publication, download, star, user or third-party-usage disclosure. It is a design roadmap for the author's own engine, with no indication that the code is public, packaged or run by anyone. Inferring adoption from a tutorial would be a guess, so this dimension is left unmeasured.
Absolute claims, no measurement
The framing runs well ahead of what the source demonstrates. A 'sub-microsecond' headline, a phase literally labelled '0ns', casts described as returning 'in nanoseconds', and a 12,000ns-to-600ns parsing improvement are all stated without any measurement, hardware or methodology, while adoption evidence is absent entirely. The underlying design choices are sound and specific, which keeps this short of maximal overstatement, but the quantitative language is unsupported by anything in the cluster.
Author-promoted, unreviewed
Observable from the source alone: this is single-author content self-published on a community platform, promoting a design and named project ('SignalPro') the author is building, with a marketing-style headline and no editorial or peer review in the loop. That alignment favours confident performance language over caveats. No sponsorship, vendor relationship, commercial offer or financial interest is disclosed in the supplied text, so the score reflects ordinary author-advocacy incentives rather than any established commercial conflict.
Clear text, narrow base
Confidence is high on what the article says and on the mechanics its code demonstrates: the text is explicit, quotable and internally consistent. Confidence is low on anything beyond that — performance, real-world behaviour, and whether the engine exists in running form — because there is exactly one self-published source, no corroboration and no adoption or measurement data. The net is moderate.
build
A supervisor rebuilt from spawn_link and receive shows where restart bugs actually live1 distinct publisher
build
Zenoh's put() returns before anyone can read it: a 3.9% stale-read rate in a tight loop1 distinct publisher
build
The failure modes of AI agents in low-level code have names, and names can be gated in CI1 distinct publisher
build
A default that is not a guard: tinycolor2's palette functions never return on analogous(-1)1 distinct publisher
Distinct publishers with included, body-backed reporting in this cluster.
dev.to
1 article · August 15, 2026