Skip to content

Navigation Menu

Sign in
Sign up
@marvelbark2
marvelbark2
Follow

Masaoudi youness marvelbark2

FullStack Dev (->) JAMStack DEV

Block or report marvelbark2

Block user

Prevent this user from interacting with your repositories and sending you notifications. Learn more about blocking users.

You must be logged in to block users.

Content in all repositories owned by your account will be closed.
Maximum 250 characters. Please don’t include any personal information such as legal names or email addresses. Markdown is supported. This note will only be visible to you.
Report abuse

Contact GitHub support about this user’s behavior. Learn more about reporting abuse.

Report abuse
marvelbark2 /README.md

Youness Masaoudi

Senior Software Engineer / Tech Lead | Paris, France

LinkedIn Email

I spend my working hours on production TypeScript and Go, and my remaining
hours writing a programming language in Rust. Both make me better at the other.


Table of contents


Ryo, a web-first language in Rust

PHP won the early web for one reason that had nothing to do with language design: it knew it was serving HTTP. Everything since has been a runtime bolted onto a general-purpose language. Ryo asks what you get if the compiler itself understands routes, shared state, background work and the database.

It started as a tree-walking AST interpreter that ran fib(40) in 81 seconds. That version is gone. So is the bytecode VM that replaced it. The current runtime compiles to bytecode and then to native code through Cranelift.

Benchmarks

Measured on the TechEmpower Framework Benchmarks harness.

Path Ryo Reference
Store query (JIT hot path) ~675k req/s -
Shared counter, parallel endpoint 189k req/s Bun: 152k req/s
/db single query 93k req/s uWebSockets.js: 89k req/s
Peak memory, large payload 15 MB Down from 650 MB

The Bun comparison is the one I find most interesting, because Ryo does not win by a large margin on median throughput. It wins at p95 and above, which is what you actually feel in production.

Runtime architecture
  • Compilation. Source to bytecode, then Cranelift IR, then native code. Both JIT and AOT backends. Binary inspection on Mach-O arm64 showed __text dominated by cranelift-codegen at around 5 MB, with a transitive wasmtime-internal-core dependency I am still working to drop.
  • HTTP. Hyper on Tokio, with SO_REUSEPORT per core so the kernel distributes accepts rather than a single acceptor thread fanning out. Thread-per-core, moving toward io_uring via Monoio after 1.0.
  • Optimisation passes. Scalar Replacement of Aggregates at the Cranelift IR level removed roughly 13 million runtime method calls from a single bytes.at hot loop. Arena allocators and prebuilt response caches are in; kernel-level profiling with flamegraphs drives the rest.
  • Memory. Heap::Bytes(Arc<[u8]>, Range<usize>) gives zero-copy slicing. The 650 MB to 15 MB reduction came from fixing a Weak pointer cycle that was keeping whole buffers alive. The Bytes API is built around next_line and next_field returning [start, end, next], backed by memchr.
Language design

The primitives are chosen around what web applications actually need, not around what is easy to compile.

  • store {} is an actor with a query / action split. It solves mutable shared state without locks in user code, and it turns out to be structurally the same thing as an Erlang GenServer, which I only realised after building it.
  • parallel {} has static and dynamic forms, so the scheduler can plan the static case at compile time.
  • schedule {} puts cron-shaped work in the language rather than in a sidecar process.
  • model {} is the ORM, with the schema in the type system.
  • html {} is a first-class type that is XSS-safe by construction. You cannot concatenate a string into it.
  • memo fn and stream fn with emit from cover caching and SSE.
  • WebSocket routes are declared like HTTP routes, alongside SSE routes with heartbeat and typed events.

Tooling ships with the language: a full LSP (diagnostics, completion, hover, go-to-definition, references, symbols, signature help, formatting), a VS Code extension, test blocks and fixture declarations inside .ryo files, and a fuzzing harness.

The grammar is formally specified in EBNF at spec/grammar/ryo.ebnf. Individual subsystems have their own written specs before implementation: lifecycle events, config and services (config desugars to resource, with a Secret<str> type), the mail service (send versus enqueue, memory transport for tests), security defaults (CSRF on by default, rate limiting with trusted_proxies) and a cache layer with a flat normalised store and O(1) read and edit guarantees behind sharded read-write locks.

What is not done

The core language is feature-complete and core HTTP hardening is in place: body limits, per-request timeouts, graceful shutdown, CORS, CSRF, rate limiting, connection caps, security headers. What is still missing before I would put it in front of real traffic: database pool backpressure, full observability defaults, supply-chain signing, documentation, and any stability guarantee at all.

The open items are tracked in roadmap/before_prod.md and summarised in spec/caution_prod.md, both in the repository. Ryo is not ready for your production traffic and I will keep saying so until it is.

-> marvelbark2/ryo-lang


Production work

Technical lead on a multi-tenant SaaS platform for sports event management. I am the principal engineer across every repository in the organisation.

Payments processed 3.8M EUR / year, 9M EUR since 2022
Registrations 190 000 over 12 months
Share of all-time volume in those 12 months 74%
Organisers on the platform 600+
PostgreSQL models under Prisma 84

That 74% number is the one that matters. Three quarters of everything the platform has ever processed arrived in the last year, and it was absorbed without a rewrite.

Change data capture: LISTEN/NOTIFY to Debezium and Kafka

Postgres LISTEN/NOTIFY is a lovely primitive right up to the point where you need durability, replay, or more than one consumer group. Migrated to Debezium reading the write-ahead log into Kafka, with Go consumers fanning out to ClickHouse for analytics and Meilisearch for search. Search latency on participant lookup dropped 40%, partly from the index being fed properly and partly from query rewriting on the read side.

A WebSocket gateway for identity verification over 3G

Race sites are fields. The network is one bar of 3G and a lot of hope. Built a Go WebSocket gateway that streams identity documents and face captures to OCR and facial recognition, chunked and backpressured for links that drop constantly. The naive HTTP upload version failed often enough to be unusable.

Payments across three gateways

Monetico, Fintecture and PayZen, each with its own opinion about HMAC signatures and webhook semantics. The interesting work is not the happy path, it is reconciliation: what you do when the webhook arrives twice, arrives late, or never arrives and the money moved anyway. Plus refunds, which every gateway models differently.

Caching in three tiers

Redis for shared hot state, Badger and Pogreb for embedded local tiers where a network hop was not worth paying for. Chosen per access pattern rather than by putting Redis in front of everything and hoping.


Performance engineering

The habit that connects everything above: measure at the level below the one you think the problem is on.

1 Billion Row Challenge, Rust and Java

Implemented independently in both, because the two languages fail in different places.

Java. SWAR temperature parsing, branchless throughout, flat open-addressed hash table, GraalVM native image to skip warmup.

Rust. read_unaligned for the parsing hot path, name addresses stored as offsets into the mapped file rather than as pointers or owned strings, and a triple-cursor hot loop to give the CPU three independent dependency chains to work on at once.

Also profiled MmapSlice against a straight Vec copy on a 13 GB input, which is where the zero-copy Bytes design in Ryo came from.

Tooling I built to do this
  • flamegraph_breakdown.py, a per-worker function-level breakdown of flamegraph output, because aggregate flamegraphs lie when your workers are not symmetric.
  • A Streamlit and Plotly benchmarking dashboard that ingests parquet and CSV so framework comparisons are reproducible rather than remembered.

Open source

Project Contribution
fullcalendar-vue Ported the component from Vue 2 to Vue 3. Merged to the vue3 branch and released as the @fullcalendar/vue3 package.
oven-sh/bun Implemented createReadStream on Bun's native Readable API, benchmarked ahead of the Node.js path. Not merged, the feature landed independently before review.
ryo-js Filesystem-routed TypeScript fullstack framework. APIs, WebSockets, GraphQL, SSE, Preact components, SPA routing. The ancestor of Ryo.
postgrest-java Java client for PostgREST.

Homelab

Built from parts: MACHINIST PR9 X99 board, Xeon E5-2699 v4, Ubuntu Server, Docker, Nextcloud, Jellyfin. It has taught me more about operations than any managed platform has.

The best lesson came from a thermal emergency. The NVMe drive hit 100 C and I could not find a workload to blame. The cause was the nouveau GPU driver flooding the kernel log at 49 000 messages per second, and the disk was cooking itself writing them down. Nothing in the application layer would ever have shown me that.


How I work

  • Read the layer below. Most performance mysteries resolve one abstraction lower than where they appear. Flamegraphs, perf, disassembly, kernel logs.
  • Throw away the first version. Ryo's interpreter, its bytecode VM, and its early Bytes API all got deleted. Keeping a bad design because it took a long time to write is the expensive mistake.
  • Benchmarks or it did not happen. A claimed speedup without a reproducible harness is a guess with good posture.
  • Write the spec first for anything with a surface area. Every Ryo subsystem has a written specification before it has an implementation. It is faster, not slower.
  • Say what is broken. See the "what is not done" section above.

Stack

Systems Rust Go C Java

Web TypeScript Node.js React Next.js GraphQL

Data PostgreSQL Redis Kafka ClickHouse Meilisearch Prisma

Infrastructure Docker Linux AWS Nginx


GitHub stats

Pinned Loading

  1. ryo-js ryo-js Public

    Js fullstack framework, Incredibly fast

    TypeScript 5 1

  2. spring-micro-services spring-micro-services Public

    Java 2

  3. fullcalendar-vue fullcalendar-vue Public

    Forked from fullcalendar/fullcalendar-vue

    An official Vue component for FullCalendar

    JavaScript 2

  4. java-network java-network Public

    Java

AltStyle によって変換されたページ (->オリジナル) /