Askr 1.0 — the whole server, in one binary
Askr hits 1.0: embedded PHP 8.5 in a Rust binary — web server, queue, scheduler, cache, and broadcaster in one process. Frozen surfaces under SemVer, four code reviews, and 23 million requests of proof.
Release notes, and a little reflection.
I still remember the first commit that mattered: a spike that proved PHP could be embedded in a Rust process and answer a request in-process — no FastCGI socket, no FPM pool, no nginx out front. It printed "hello" and exited. It felt like cheating.
Today Askr is 1.0. Same idea, grown all the way up.
What Askr is
Askr is the entire PHP application server as one binary. You point it at a Laravel app and it serves it — embedded PHP 8.5 (non-ZTS, OPcache + JIT), one worker process per core, no FPM, no nginx, no Redis. That last part is the one people don't quite believe at first, so let me be specific about what "no Redis" means:
Sessions, cache, atomic locks — a shared-memory hash table mapped before the fork, so every worker sees the same data with zero network hops.
Queues + a scheduler — a shared-memory job table with delays, retries, and backlog-driven worker autoscaling.
queue:workandschedule:runare just supervised children.Broadcasting — SSE and a Pusher/Reverb-compatible WebSocket endpoint, fanned out from a shared ring so a publish from any process reaches every subscriber.
Drop in kwhorne/askr-laravel, set four .env lines to askr, and the Redis-shaped hole in a typical Laravel deployment closes. One binary does the web server, the queue worker, the scheduler, the cache, and the broadcaster.
And because Askr owns the whole request lifecycle — it isn't shouting at PHP across a socket — it can do things a proxy in front of FPM structurally cannot:
Response cache with instant tag invalidation, request coalescing (singleflight), and stale-while-revalidate — all in the Rust layer, compressed once.
HTTP/1.1, HTTP/2, and HTTP/3 over QUIC, sharing one cert and one request handler. Your PHP app doesn't know which transport it's on.
Streaming PHP output: call
flush()and Askr streams each chunk to the client as you produce it — SSE,StreamedResponse, big exports — with back-pressure that pauses PHP if the client is slow.Observability you already have, not integrations you bolt on: per-request logs and a metrics rollup streamed to a MySQL-wire database, plus OpenTelemetry traces where you can literally see that PHP is 99.5% of the request.
Auto-TLS via ACME, with hot-reload when an external cert renews on disk.
Multi-domain hosting — several domains and apps from one instance, with www→apex and http→https redirects, so you're not running one Askr per site on a shared box.
All of it self-contained, memory-safe at the edges, and Linux-hardened with seccomp + Landlock when you ask for it.
What 1.0 actually means
1.0 is not a pile of new features. It's a promise.
For the whole 0.x series I told you the surfaces were stable "in practice" but not guaranteed. Now they are. From this release, the CLI flags, the askr.toml keys, the ASKR_* environment variables, the askr_* functions injected into PHP, the reserved HTTP surface, and the build features are frozen under SemVer. Breaking any of them requires a 2.0 and a deprecation cycle — add first, warn for a full minor series, remove only at the next major. It's written down in STABILITY.md, and I mean it.
That's the real gift of a 1.0: you can build on Askr without watching the changelog with one eye.
Earning it
I didn't want to slap a "1.0" on something that hadn't been leaned on. So before the tag, Askr went through the wringer.
Four separate source-code reviews — sharp ones — each verified line by line against the source. Some findings were real and got fixed with a test: a tombstone-deletion bug in the shared-memory cache that could hand out a lock twice; an admin plane that needed a bearer token; an upload temp dir that should be 0700; a worker crash-loop that should fail fast instead of burning a core forever. Some findings were wrong, and I said so with evidence rather than quietly "fixing" a non-bug — the "DefaultHasher uses random keys" claim, for instance, disproved with three processes printing identical hashes.
Then a stress campaign in a local container stack. Tens of millions of requests. A ten-minute soak serving 23 million requests across two domains at 100% success with bounded memory. And — quietly satisfying — the observability sink, which had shipped months earlier as "code-complete but never verified against a real database," finally proven end-to-end against ElyraSQL: three million log rows written, the metrics rollup aggregating 23.7 million requests across 85 windows, and back-pressure correctly dropping telemetry under 60k req/s so it never once slowed a real request. The thing I'd been unable to test for a long time just worked, because ElyraSQL speaks the auth dialect the driver needed.
The honest numbers are in BENCHMARKS.md, including the one that changed the roadmap: PHP is ~99.5% of a request and I/O is ~0.5%, which is why the long-planned io_uring core got deprioritised by its own data. Measuring beats guessing, every time.
Thank-yous and honesty
A few things are still exactly what they say on the tin. CoW template mode is marked experimental because it is. Multi-site does full dynamic dispatch in per-request mode; running several Octane apps in one instance is future work, and the docs say so. I'd rather under-promise in writing than surprise you in production.
Where this goes
1.0 is a frozen, stress-validated base — not an ending. The issue tracker has the next horizon: per-site worker pools, a durable-tier polish pass, and some genuinely fun experiments (semantic AI-response caching in shared memory, a Varnish-grade edge cache, a P2P cluster mesh). All of it now under the stability guarantees, so the foundation stays still while the interesting stuff grows on top.
But today is for the milestone. From a spike that printed "hello" to a stable server that runs real Laravel, speaks h3, replaces Redis, hosts your domains, and streams its own output — one binary, memory-safe, no FPM, no nginx.
docker pull ghcr.io/kwhorne/askr:1.0.0 # or :latest
# full build (L2 + observability + OTel + HTTP/3):
docker pull ghcr.io/kwhorne/askr:1.0.0-full
composer require kwhorne/askr-laravel
Askr is 1.0. Thanks for reading along the way. 🌳