kevy4.0

Ship it inside

Put the store
inside the thing

No server, no socket, no network. The engine is a struct you call, a 151 KB WebAssembly module, or a no_std library on a chip with no operating system — and it is the same engine, with the same commands, in all three.

Why this fits

Every application that has to work offline ends up writing a storage layer. A desktop app gets SQLite and a schema nobody wanted. A web app gets localStorage, discovers the 5 MB ceiling and the fact that it is synchronous and string-only, and then gets IndexedDB and an abstraction over it. A device gets a hand-rolled ring buffer in flash.

All three are the same problem, and they can be the same solution. kevy embeds with no process boundary, ships to a browser with real TTLs and pub/sub, and boots on a Cortex-M with a fixed arena and no allocator at all. CI proves the last one on every push.

How — inside a Rust program

No socket, no serialisation, no second process. Durable, and it replays its log on open.
kevy-embedded = "4.0"

let db = Db::open("data/")?;
db.set(b"session:7f3a", b"{\"user\":\"ada\"}", Some(Duration::from_secs(3600)))?;
assert_eq!(db.get(b"session:7f3a")?.is_some(), true);

// need other processes to reach it later? open the RESP listener
// and your redis-cli works, without changing any of the above.
db.listen("127.0.0.1:6379")?;

How — in a browser tab

151 KB gzipped. Persists to the browser's own filesystem, survives a reload, and speaks pub/sub across tabs.
import { open } from "@goliajp/kevy";

const db = await open({ persist: { name: "app" } });

db.set("cart:u881", JSON.stringify(items), { ttlMs: 86_400_000 });
db.get("cart:u881");        // still there after a reload
db.pttl("cart:u881");       // the engine expires it, not your code

db.subscribe("sync", (payload) => merge(payload));   // other tabs

How — on a microcontroller

no_std, no allocator, no operating system. A fixed arena you size yourself.
# Cargo.toml
kevy-store = { version = "4.0", default-features = false }

# no_std, no heap: the store lives in an arena you provide
let mut arena = [0u8; 64 * 1024];
let mut store = Store::new_in(&mut arena);
store.set(b"temp", b"21.4")?;
What it costs you

In the browser, localStorage is faster for a small synchronous read — it is a map in the page's own address space and nothing built on OPFS will beat it at that. kevy wins on everything that makes localStorage a bad idea anyway: real TTLs, no 5 MB ceiling, byte values rather than strings, and writes that do not block the main thread. On a microcontroller you size the arena yourself and there is no growing it at runtime — that is what no allocator means. And an embedded store is not shared: if a second process needs the data, you want the server, or the embedded RESP listener.

Next