[Plugin Announcement] gojinn: Ultra-low latency Serverless Runtime (Wasm) for Caddy

Hi everyone,

I’m excited to share a project I’ve been working on: Caddy Reactor.

Repository: GitHub - pauloappbr/gojinn

What is it?
Reactor allows you to run Go, Rust, Zig, or Swift code directly inside your Caddy HTTP request flow using WebAssembly (via wazero).

It acts like a “self-hosted Cloudflare Workers” or “AWS Lambda”, but running in-process.

Why use it?
I built this to solve the gap between writing a native Caddy module (complex, unsafe memory sharing) and running a sidecar container (high latency/overhead).

Key Features:

:high_voltage: Fast: Cold starts are <1ms (compared to ~1.5s for Docker containers).

:shield: Safe: Each request runs in a strict sandbox. If your handler crashes or loops infinitely, Reactor kills it without affecting Caddy.

:chart_decreasing: Efficient: Zero memory footprint when idle.

:electric_plug: HTTP Parity: Full control over Headers, Status Codes, and Body via a simple JSON protocol.

Benchmarks (Docker vs Reactor)
We ran a stress test calculating taxes on a JSON payload.

Docker Cold Start: ~1500ms

Reactor Cold Start: ~1ms :trophy:

Artifact Size: 20MB (Docker) vs 3MB (Wasm)

How to use
Snippet de código

:8080 {
handle /api/* {
reactor ./functions/auth.wasm {
timeout 2s
memory_limit 50MB
env SECRET “my-key”
}
}
}

I would love to get feedback from the community. It’s currently in v0.1.0, implementing the core runtime and HTTP context switching.

Thanks! Paulo Henrique

5 Likes

This looks really cool, thank you for building and sharing!

1 Like

Thanks so much, Matt! Hearing this from you is a huge motivation! :raising_hands:

I wanted to share a quick update: I’ve just rebranded the project to Gojinn (formerly Reactor).

I realized “Reactor” conflicts heavily with the Java/Spring ecosystem (Project Reactor), and I wanted this project to have a unique, distinct identity within the Caddy ecosystem.

Gojinn (Go + Djinn) represents the concept better: Caddy is the Lamp (the sandbox), and Gojinn is the Genie that pops out, executes the wish (the code) instantly, and vanishes. :man_genie:

The repository has been renamed to GitHub - pauloappbr/gojinn (redirects from the old link are working).

I’m looking forward to adding more features like connection pooling soon!

2 Likes

This does look interesting.

Are there use-cases where gojinn especially shines?

Would gojinn be another way to write server-side HTMX handlers?

Is gojinn opinionated about the WASM run-time used?

Can gojinn permit a choice of WASM run-time like with node, deno or bun in the JS/TS ecosystem?

2 Likes

Thanks for the interest! Let me break down your points, because you actually touched on a great use case with HTMX.

1. Where does Gojinn shine?

Gojinn shines in high-density, low-latency scenarios where a full container (Docker) is overkill, but a native Caddy module (written in Go) is too rigid because it requires recompiling Caddy.

  • Webhooks & Glue Code: Processing thousands of events from Stripe/GitHub where you just need to validate a signature, transform JSON, and forward it.

  • Edge Logic: Custom authentication, header manipulation, or complex A/B testing logic that runs directly in the web server process.

  • ​**“Scale to Zero”:** Hosting 500 different little functions on a cheap VPS. Since they are just .wasm files, they consume zero memory when idle.

2. Server-side HTMX handlers?

Absolutely YES. This is actually one of the best use cases.

Since Gojinn runs in-process with Caddy, it can generate and return HTML fragments (using Go html/template, Rust Askama, or TinyGo) with sub-millisecond latency. It eliminates the network hop between the Web Server (Caddy) and the Application Server (e.g., Python/Node), making the UI feel instant.

3. Is it opinionated about the Runtime? (Why wazero?)

Yes, Gojinn is strictly built on wazero.

The reason is architectural alignment with Caddy: Pure Go (No CGO).

  • ​Other runtimes (like Wasmtime or Wasmer) are written in Rust/C++ and require CGO to run inside a Go program. This breaks Caddy’s ability to be a single, static, cross-platform binary.

  • ​By using wazero, Gojinn keeps Caddy 100% Go, portable, and easy to build.

4. Can I choose the Runtime?

You cannot swap the engine (it will always be wazero for the reasons above), but you have total freedom over the Language.

You can write your handlers in Go, TinyGo, Rust, Zig, C++, or Swift. As long as it compiles to WASI (WebAssembly System Interface), Gojinn will run it.

1 Like