Igropyr
A web server where crashes heal themselves,
code hot-swaps, faults speak a protocol, and
dialogues are processes.
Pure Chez Scheme · Erlang-style actors · libuv event loop · MIT
Let It Crash
Every request runs in a supervised worker pool.
Handlers don't defend — they crash, and the system recovers.
Crashes heal themselves
A crashed worker is replaced instantly; the task is
retried on a fresh worker, up to 3 times, before the client
sees an error.
A worker stuck longer than 30 s — even a CPU-spinning
loop — is killed and replaced: preemptive scheduling
means nothing can freeze the server.
A half-sent request parks only its own reader process
and is reaped by timeout. Other connections never notice.
Write the happy path. The supervisor owns the sad one.
Hot code swapping
Replace the handler — or a single route — on a running
server. The listener, open connections and the worker pool stay up;
in-flight requests finish on the old code.
Deploy without a restart
Routes live in a mutable registry behind the pool. Re-registering
a path replaces it atomically for the next request;
http-swap! replaces the whole handler the same way.
Combined with graceful shutdown (http-shutdown!
drains in-flight work) and SO_REUSEPORT multi-process
listening, zero-downtime operation is the default, not a project.
Faults speak a protocol
When retries are exhausted or a stuck worker is killed,
Igropyr doesn't just throw a 500 — it can tell the client exactly
what happened, on a connection that stays open.
Killed first, told after
The on-failure hook answers a structured fault
after the stuck worker is dead — so when the client hears
stuck, there is no execution left in flight.
The state is definite.
crash — retries exhausted; resubmit with changed
parameters, or compensate.
stuck — killed mid-flight; resubmit carrying state,
or roll back.
Keep-alive survives the fault, so the client resubmits on the
same connection and gets a fresh retry round. Shorten
stuck-ms and a user who once stared at a spinner
for 30 s now rings through several informed retries in the
same time — failures become invisible at the UI.
Dialogues are processes
A multi-request dialogue — a wizard, a booking, a
transfer — runs as one green process. Its local bindings are
the conversation state, including things a session store can never
hold: an open database transaction, spanning rounds.
Control flow is program text
"The user is at the confirm step" means the process is parked
at that line. A step order the code cannot express cannot
happen — no state machine to get wrong, no replay to defend
against.
The gone guarantee: death for any reason —
crash, TTL, completion — unregisters the process, and a later
resume answers gone. Dead process = dropped
connection = the database itself rolled back:
gone proves nothing committed. Together with
the fault codes above, the client always knows the definite
server state — a complete remote transaction ring.
What it stands on
Pure Chez Scheme
Every line is Scheme — R6RS libraries in .sc, no C
shim. libuv, zlib and the crypto for MySQL auth are reached
through Chez's FFI directly. Whole-program compilation folds the
framework and your app into one optimized binary.
Erlang-style actors
Green processes with spawn / send / receive,
link and monitor, a process registry,
gen-server and PubSub. One OS thread, preemptive
scheduling, pure message passing — no shared state, no locks.
Async on libuv
One event loop feeds thousands of parked processes. DNS, file
reads and database round-trips park the calling process,
never the thread. Non-blocking HTTP/WebSocket clients and
Redis/MySQL drivers included.
Built on the shoulders of others
Igropyr is built on Chez Scheme — the fastest
Scheme compiler, with a first-class FFI that reaches libuv directly.
With deep gratitude for Kent
Dybvig's life work, and to Cisco for open-sourcing
it.
[Kent
Dybvig](https://github.com/dybvig)
The primary inspirations: Node.js is the event-loop server on
libuv, and the lean core / optional-framework split that Node and
Express made the norm. The actor model, the supervisor, and
Let It Crash come from Erlang/OTP; Swish — a
Chez Scheme system built on those ideas — was the concrete
blueprint for the scheduler, the receive macro, and the
supervisor. The conversation model is the actor-native take on
web programming with continuations — a great idea from the
Scheme and functional-programming community.
![]()
![]()