Stream: show and tell

Topic: roux: a no-compromise Roc web platform


view this post on Zulip Zak Kohler (Oct 16 2026 at 02:19):

Roux

Roux is a web platform for Roc that includes everything you need to deploy.

image.png

Fast, and raced every night against Go, Rust's axum, and basic-webserver. Rendering a template, roux serves about 1.9× axum's requests and 7.5× Go's, within 6% of fourneau, the raw Zig server it's built on:

image.png

Over TLS it serves 168,700 requests/s, to axum's 80,700.
The latest results: https://fourneau.y2kbugger.com/

Try it in a minute. The tutorial is itself a roux app, and that live reload timing is its first page: https://github.com/Eldhus/roux-tutor

view this post on Zulip Luke Boswell (Oct 16 2026 at 02:37):

Couldn't help myself ... had to make a click bait post on Reddit :grinning_face_with_smiling_eyes:

https://www.reddit.com/r/roc_lang/comments/1x74nx2/how_is_this_new_web_framework_so_fast/

view this post on Zulip Zak Kohler (Oct 16 2026 at 02:40):

The answer is some combination of: io_uring+shards, lack of features, and deceiving myself somehow.

view this post on Zulip Luke Boswell (Oct 16 2026 at 02:43):

I really appreciate the effort you have put into making it polished and sharing it. Looks really nice.

view this post on Zulip Zak Kohler (Oct 16 2026 at 02:50):

Definitely be sure to checkout the "dragrace" site its pretty fun to click through and compare. I'm sure the other platforms have a bunch of low hanging fruit to compete better too (looking at basic-webserver).

https://fourneau.y2kbugger.com

image.png

view this post on Zulip Richard Feldman (Oct 16 2026 at 03:47):

this is really exciting! The hot loading with errors in the browser looks awesome, and the benchmarks are really impressive :rocket: :rocket: :rocket:

view this post on Zulip Zak Kohler (Nov 03 2026 at 16:34):

Update!

Two new features

  1. Roc flavored template holes ({{...}})
  2. and inline fragments.

Holes as Roc expressions

## A price in hundredths: `12.05`, written as a stress test/poc
kr : U32 -> Str
kr = |hundredths| {
    cents = hundredths % 100
    pad = if cents < 10 "0" else ""
    "${(hundredths // 100).to_str()}.${pad}${cents.to_str()}"
}

expect Fmt.kr(1205) == "12.05"
{{#dishes |dish|}}<li>{{ dish.name }}: {{ Fmt.kr(dish.price) }}</li>{{/dishes}}

Inline Fragments

Fragments are inline partials that can be rendered on their own, and have their own inferrered or hinted context type.

Before, to swap one row over Datastar or htmx, you moved it to its own partial file:
Row.rocstache

<li id="dish-{{ dish.id.to_str() }}">{{ dish.name }}: {{ Fmt.kr(dish.price) }}</li>

Page.rocstache

{{#dishes}}{{> Row .}}{{/dishes}}

Now it stays where it is and renders alone too:
Page.rocstache

{{#dishes |dish|}}
  {{$Row}}<li id="dish-{{ dish.id.to_str() }}">{{ dish.name }}: {{ Fmt.kr(dish.price) }}</li>{{/Row}}
{{/dishes}}
"/row" => Ok(Rocstache.html(Menu.Row.template(dish)))

Menu.Row.Ctx is just what it reads: { id : U64, name : Str, price : U32 }.

Docs: https://github.com/Eldhus/roux/blob/master/docs/templates.md

The downside is that we are now losing to Axum in the dragrace for the most intesive template test, but I have two small-string PRs on built-ins that close that gap. https://github.com/roc-lang/roc/issues/12824
I also mention that that string interpolation has a lot left on the table perf-wise, but I'm sure this is known and rightfully deffered to a later time.

view this post on Zulip Richard Feldman (Nov 03 2026 at 18:10):

I haven't really looked into string interpolation perf - do you know offhand what's inefficient about it at the moment?

view this post on Zulip Richard Feldman (Nov 03 2026 at 18:11):

I'm doing perf stuff now but plan to stop that in favor of bugfixes only pretty soon, so now's the time for fixes like that :smile:

view this post on Zulip Notification Bot (Nov 04 2026 at 14:40):

17 messages were moved from this topic to #show and tell > Rocstache: small string concat perf by Zak Kohler.


Last updated: Nov 04 2026 at 18:54 UTC