Moonbeam
A single-threaded-first async HTTP/1.1 server written in Rust.
Moonbeam is designed to be simple, efficient, and free of synchronization overhead by running on a single thread. It leverages the async-io and smol ecosystem to handle concurrent connections asynchronously. By default, it uses a "share-nothing" architecture, avoiding the need for Arc, Mutex, or Send/Sync bounds on your state, though it can easily be extended to multiple threads if desired.
Motivation
Modern web applications often spend most of their time waiting on I/O (databases, network requests, etc.) rather than performing heavy CPU computation. Moonbeam embraces this by running your application logic on a single thread, utilizing a local executor. This means you can use simple RefCell and Cell primitives for state management, drastically reducing the cognitive overhead and boilerplate often associated with multi-threaded Rust web frameworks.
Critical Considerations
Before building with Moonbeam, it's essential to understand its execution model:
- No Tokio: Moonbeam is built on
async-ioand thesmolecosystem. It does not usetokiodependencies. This means notokio::spawn, no#[tokio::main], and no tokio-specific database drivers (unless they supportasync-ioorsmol). - Blocking I/O: Because Moonbeam runs handlers on a
LocalExecutoron the main thread, any CPU-heavy computation or blocking I/O (like reading a large file synchronously) will block the entire server.- Solution:
smolsupports async I/O via theblocking::unblockprimitive for offloading heavy tasks to a background thread pool, or you can use theasync_iocrate for native non-blocking operations.
- Solution:
Features
- Single-threaded by default: No
ArcorMutexneeded for shared state. - Multi-threaded support: The
mtfeature spawns worker threads, each with its own state copy. - Simple API: Use the
#[server]macro to turn functions into server handlers. - Routing: The
router!macro provides a clean DSL and efficient implementation for nested groups, middleware, path parameters, and wildcards. - Typed Body Extractors: Use
FromRequestandFromBodytraits for zero-copy, asynchronous body parsing (e.g., JSON). - Static Assets: Built-in
assetshelper for serving files with ETags and MIME type detection. - HTTP/1.1: Persistent connections, chunked transfer encoding, and standard header parsing.
- Zero-cost extractions: Efficient parsing of Cookies, Query Parameters, and Bodies.
- Panic Handling: Optional
catchpanicfeature safely catches panics and returns a 500 error. - Response Compression: On-the-fly
compresssupport (Gzip, Brotli, Zlib). - Graceful Shutdown: Intercepts
signalsfor clean exit. - TLS Support: Secure your server with
rustls(behind thetlsfeature).
Is it fast?
Yes. Moonbeam is designed for high performance with minimal overhead. In simple benchmarks using wrk (4 threads, 100 connections, 5 seconds), Moonbeam shows competitive performance for both simple responses and static file serving.
The below benchmarks were performed on a MacBook Pro (M3 Pro). While these simple tests don't represent real-world application complexity, they demonstrate the efficiency of Moonbeam's core request/response loop.
Hello World (Plain Text)
| Framework | Architecture | Requests/sec |
|---|---|---|
| Axum (Tokio) | Multi-threaded | ~216,000 |
| Moonbeam | Multi-Threaded (4 cores) | ~214,000 |
| Moonbeam | Single-Threaded | ~211,000 |
| Node.js | Single-Threaded | ~117,000 |
| Rouille | Thread-per-connection | ~93,000 |
Static File Serving (4KB file)
| Framework | Architecture | Requests/sec |
|---|---|---|
| Moonbeam | Multi-Threaded (4 cores) | ~73,000 |
| Moonbeam | Single-Threaded | ~66,000 |
| Axum (Tokio) | Multi-threaded | ~58,000 |
| Rouille | Thread-per-connection | ~56,000 |
| Node.js | Single-Threaded | ~51,000 |
Build Times & Install Size
Moonbeam also offers relatively fast compilation times and a small disk footprint. For the simple benchmarks:
| Framework | Clean Build Time | Install Size (Avg) |
|---|---|---|
| Moonbeam | ~4.6s | ~926 KB |
| Axum (Tokio) | ~8.6s | ~1.6 MB |
| Rouille | ~8.9s | ~933 KB |
| Node.js | 0s | ~78 MB |
Note: The Node.js benchmark does not require any build step and relies entirely on built-in standard library modules. However, the Node.js runtime itself typically requires an installation footprint of around 50–100 MB depending on the platform.
Installation
Add moonbeam to your Cargo.toml:
[]
= "0.7"
Feature Flags
Moonbeam is configurable via Cargo features. Most users will want the default features.
default: Enablesmacros,assets,catchpanic,signals, androuter.macros: Enables the#[server]attribute macro to easily createServertrait implementations.assets: Exposes themoonbeam::assetsmodule for serving static files.signals: Hooks into OS signals (SIGINT, SIGTERM) to trigger graceful server shutdown.catchpanic: Wraps your handlers to catch panics gracefully and return500 Internal Server Error.tracing: Instruments the core server loop withtracingspans and events.compress: Enables automatic response compression. (Depends onflate2andbrotli).router: Enables the routing macros (#[route],#[middleware], androuter!).mt: Exposesserve_multito run multiple independent server isolates across available CPU cores.tls: Enables HTTPS support viarustls. Exposesserve_tls,serve_multi_tls, andTlsConfig.
Configuration
Moonbeam honors the following environment variables:
MOONBEAM_MAX_BODY_SIZE: Maximum size (in Kilobytes) of an incoming HTTP request body. Defaults to1024(1MB). Exceeding this returns a413 Content Too Large.
Examples
Stateless Server
The simplest way to use Moonbeam.
use ;
async
Stateful Server (Interior Mutability)
Because the executor runs locally, you can use std::cell::Cell without Mutex.
use Cell;
use ;
async
Avoiding Macros
If you prefer not to use macros, the same examples above can be easily achieved with only slightly
more boilerplate. Make sure to update Cargo.toml to disable default features:
[]
= { = "0.7", = false }
use Cell;
use ;
Multi-threaded "Share-Nothing" Server
Use the mt feature flag to scale across multiple CPU cores.
use ;
use ;
async
HTTPS Server (TLS)
Secure your server using the tls feature.
use ;
async
Advanced Routing
The router! macro provides a clean domain-specific language for nesting routes and middleware.
use ;
use PathParams;
// Global Middleware
async
// Scoped Middleware
async
// Extractor Handler
async
async
JSON Parsing (Typed Body Extraction)
Use the moonbeam-serde crate for flexible, typed body extraction. This supports zero-copy deserialization by borrowing directly from the request buffer.
use ;
use Json;
use ;
async
HTML Forms (URL-Encoded and Multipart)
Use the moonbeam-forms crate to parse incoming form data, including file uploads.
use ;
use ;
async
Serving Static Files
use ;
async
License
This project is licensed under the MIT License.