Yuneta Simplified / Documentation / v7.8.7 · MIT · Linux

Nothing happens except through the machine.

Yuneta is an asynchronous framework for long-lived, message-driven services on Linux. Every component is a finite state machine. Every interaction between two of them is a typed event carrying JSON. That single constraint is what keeps a system enumerable, replayable and observable months after you deployed it.

state × event action the whole contract
trace C_TCP^server-1 set-global-trace level=machine
ST_STOPPED ST_DISCONNECTED ST_WAIT_CONNECTED ST_WAIT_HANDSHAKE ST_CONNECTED ST_WAIT_STOPPED

    Real states and events of C_TCP. Turn this on in any running yuno with ycommand — the trace is the execution log.

    What you are getting

    Overview

    Yuneta collects data from many devices and protocols at once, routes and adapts messages between systems, persists everything it sees as time-series and graphs, and exposes a control plane so you can inspect and steer a running process without restarting it. Most frameworks optimise one of those axes; Yuneta does all of them on one conceptual core.

    It is built for bare metal — edge boxes, IoT gateways, plain servers. Binaries are fully static by default: no shared libraries, no dynamic linker. Copy a compiled yuno to any Linux machine of the same CPU architecture and it runs, with nothing to install.

    The C implementation is the reference. A JavaScript implementation shares the same GClass layout and the same public API, so a browser frontend drives a C backend with byte-identical payloads — no generated glue in between.

    Version
    7.8.7
    Languages
    C (reference) · JavaScript
    Platform
    Linux · bare metal · ESP32 port
    I/O engine
    io_uring
    Concurrency
    one thread per yuno
    Payloads
    JSON, everywhere
    Storage
    append-only time-series
    Linking
    fully static
    License
    MIT

    Five decisions, and what each one costs

    /design-principles

    Every framework publishes its advantages. These are the same decisions with the bill attached, because picking a framework means picking its trade-offs. Three more are documented in full on Design Principles.

    Decision 01events & FSM only

    There are no methods. There is no way to call another object.

    Every interaction is an event: a typed name plus a JSON payload. Every gobj is a state machine whose GClass declares the states, the events each state accepts, and the action that runs. Behaviour becomes enumerable — you can draw the diagram, replay the log, and fuzz every transition.

    Trade-offYou have to design the states up front. Yuneta will not let you just call a method on the object next door.

    Decision 02one thread per yuno

    No locks, no mutexes, no atomics anywhere in the framework.

    A yuno is a single-threaded process. You scale by running one yuno per CPU core and passing events between them. That deletes a whole category of bugs: data races, deadlocks, priority inversion, cache-line ping-pong.

    Trade-offA single slow operation blocks its yuno. Work has to be split across processes, not threads.

    Decision 04JSON in flight

    One format for payloads, records, logs, commands and stats.

    There is no "struct for speed, JSON for the wire" split. One serializer, one schema tool, one debug printer, one diff, one test assertion. It is also why the C and JavaScript sides exchange messages without generated code.

    Trade-offParsing is not free. Yuneta targets many thousands of messages per second per core, not tens of millions.

    Decision 07append-only, graph on top

    One storage primitive, several views of it.

    timeranger2 writes append-only records per topic and per key. The durable queue, the dict store and the in-memory TreeDB graph are all built on that same log — which is what buys you crash safety, audit trails and replay.

    Trade-offYou trade disk for keeping everything; there is no in-place rewrite. Files are time-segmented, so archiving old data is an ordinary file copy.

    Decision 08control plane is first-class

    Every gobj is operable the day you write it.

    Commands and stats are declared on the GClass, next to the attributes. Operators reach them over a local socket with ycommand; other yunos send the same commands as events. Same surface either way, no separate management interface to design.

    Trade-offEvery public command is part of your API. You version and authorize it like any other contract.

    Measured, not claimed

    /benchmarks
    35,760op/s TCP echo through the full gobj protocol stack. perf_tcp_test4
    24,862op/s The same echo, TLS-encrypted end to end. perf_tcps_test4
    173,000msg/s Raw io_uring ping-pong, 177 MB/s, no gobj overhead. perf_yev_ping_pong
    1,500,000conns Concurrent TCP connections held by one listener. stress_listen

    Figures from the reference box. Every performance binary is a ctest target — run yunetas test and get your own numbers.

    Read it in this order

    Seven steps

    The sidebar has everything, but the order below is the one that works: why before what, what before how.

    The whole site

    Table of contents