Get Started
← All Posts

The Anti-Bloat Stack: Rust, HTMX, SQLite, and Caddy

Why we rejected microservices and SPAs to build a commenting engine that actually respects your server and your users.

The Anti-Bloat Stack: Rust, HTMX, SQLite, and Caddy

When we set out to build MarkReply, the default industry advice was predictable: spin up a React single-page application, deploy a heavy Node.js backend, and wire it up to a managed Postgres cluster.

For a commenting engine, that architecture is a massive over-engineering trap. It introduces network latency, inflates cloud bills, and pushes the compute burden onto the reader’s browser.

We wanted a system that was fiercely protective of both client-side performance and operational infrastructure. Here is the anti-bloat stack we chose instead.

1. 🦀 Rust (Axum): Predictable Performance

A commenting widget is fundamentally an I/O bound, highly concurrent system. It sits on other people’s websites, meaning traffic can spike from 10 to 10,000 concurrent requests the second a post goes viral on Hacker News.

We chose Rust—specifically the Axum framework—because it offers mechanical sympathy with the hardware.

  • Zero GC Pauses: We don’t have to worry about garbage collection spikes halting the event loop during traffic surges.
  • Memory Footprint: The entire backend runs in a fraction of the RAM required by a traditional Node.js or Python service.
  • Fearless Concurrency: Rust’s strict compiler guarantees mean we can handle massive connection pools without race conditions.

2. 📡 HTMX: The 14KB Frontend

The trend of sending empty HTML files to the browser and relying on 500KB of JavaScript to hydrate the UI is entirely backwards for a comment thread.

By using HTMX, we shifted the rendering logic back to the Rust server. When a user clicks “Reply”, HTMX simply intercepts the click, sends an AJAX request to the Axum backend, and swaps the resulting HTML snippet directly into the DOM.

No virtual DOM, no heavy state management, and no build steps. Just 14KB of client-side code that allows the widget to load instantly on any device.

3. 🛢️ SQLite: The Embedded Powerhouse

From an operations perspective, managing a separate database cluster for a read-heavy workload introduces unnecessary network hops and maintenance overhead.

We rely on SQLite. Because it runs in the exact same process as the Rust application, latency between the app and the database is virtually zero.

Modern SQLite, configured with WAL (Write-Ahead Logging) mode, can easily handle tens of thousands of concurrent reads and serialized writes. It simplifies our disaster recovery to a basic file backup, completely eliminating the need for expensive managed database tiers.

4. 🛡️ Caddy: The Edge

To tie it all together, we needed a reverse proxy that didn’t require complex, brittle configuration files.

Caddy sits at our edge, providing secure, automatic HTTPS by default. Because of Caddy’s dynamic API and On-Demand TLS capabilities, we can instantly provision custom domains for our multi-tenant SaaS without ever reloading the server or writing custom Certbot cron jobs.

📊 The Result

By combining Rust, HTMX, SQLite, and Caddy, we didn’t just build a faster widget. We built an incredibly resilient, self-contained architecture that radically reduces operational complexity.

It proves that you don’t need a massive, distributed microservice architecture to build a highly scalable SaaS. You just need the right tools for the job.