Building backend services, infrastructure, and developer tools requires four things at once: simplicity, memory safety, predictable performance, and fast iteration. Most approaches force a trade-off:
Mako's position is practical: you should not have to choose between safety and simplicity. The language is designed so that the common case is both safe and concise, with explicit annotations only where they genuinely prevent bugs.
Memory safety without a mandatory garbage collector. Simple structured concurrency. Fast compiles. Clean error handling. Single-binary deployment. A strong standard library. Great tooling from day one.
These are not aspirational goals -- they are the shipped reality of Mako 0.1.0.
Mako favors explicit, readable code. There are no implicit conversions between
numeric types. Assignment (=) and equality (==) are visually distinct.
Control flow uses braces and does not rely on indentation. The formatter
(mako fmt) enforces a single canonical style so teams never argue about
formatting.
fn classify(code: int) -> string {
match code {
200 => "ok",
404 => "not found",
500 => "server error",
_ => "unknown",
}
}
The ownership system (hold and share) catches use-after-move, double-free,
and data races at compile time. Result types are enforced -- you cannot silently
ignore a fallible operation. The compiler rejects programs that would have
undefined behavior, before any code runs.
fn safe_divide(a: int, b: int) -> Result[int, string] {
if b == 0 {
return error("division by zero")
}
Ok(a / b)
}
fn main() {
// This line would be a compile error if uncommented:
// safe_divide(10, 0) // error: unused Result
let r = safe_divide(10, 0)
match r {
Ok(v) => print_int(v),
Err(e) => print(e),
}
}
Mako achieves memory safety without a tracing garbage collector. Instead, it uses three complementary mechanisms:
defer statements run cleanup in LIFO order.hold bindings enforce move semantics. When a value
is moved, the original binding becomes unusable -- caught at compile time.This means no GC pauses, no stop-the-world events, and predictable latency under load.
Mako compiles .mko sources to C, then invokes clang. This pipeline is fast:
incremental builds recompile only changed translation units. Parallel object
compilation (mako build -j 8) scales with cores. The result is a tight
edit-compile-run loop even for large projects.
mako build --release produces a statically-linked native binary. No runtime
to install on the target machine. No dependency conflicts. Copy the binary,
run it. This is ideal for containers, edge deployments, and distribution to
end users.
The standard library covers the common needs of backend development:
You should be able to build a production service without reaching for third-party packages for basic functionality.
Concurrency in Mako is structured through crew blocks. A crew spawns tasks
that must all complete before the crew exits. Combined with typed channels
(chan[T]) and actors, this makes concurrent programs easy to reason about:
no dangling goroutines, no fire-and-forget spawns leaking resources.
fn main() {
let ch = make(chan[int], 4)
crew {
spawn { send(ch, 42) }
spawn {
let v = recv(ch)
print_int(v)
}
}
// crew exits only when both spawns complete
}
Session-shaped servers -- long-lived connections, real-time messaging, deterministic response times -- benefit from Mako's lack of GC pauses and its arena-based memory model. Each request allocates from its own arena; cleanup is a single pointer bump reset.
REST APIs and gRPC services benefit from fast startup (native binary, no runtime warm-up), small memory footprint, and straightforward deployment (one file to copy).
Proxies, load balancers, and protocol implementations benefit from low-level control over memory layout combined with high-level safety guarantees. Mako gives you both without forcing you to choose.
Command-line tools benefit from instant startup, single-binary distribution, and cross-compilation to multiple targets.
Batch processing and streaming systems benefit from predictable memory usage, arena allocation for per-record work, and straightforward concurrency via crews and channels.
As of the current release:
| Claim | Meaning |
|---|---|
| Version 0.1.0 | First public release, core language complete |
| Stdlib coverage | Major backend areas covered (HTTP, TLS, JSON, SQL, etc.) |
| Test suite | 130+ examples pass in the test suite |
The language is usable for real work today. Some areas are still maturing (full Unicode support, reflection, advanced generics). These are tracked in STATUS.md.
If you are new to Mako, read chapters 2 through 6 in order. They build on each other:
Once you have the foundations, jump to chapters 7 through 10 when building services. Use chapter 14 as a recipe index when you need to accomplish a specific task.
When something looks wrong or you are unsure about syntax, run mako check on
your code. The compiler is always the source of truth.
Next: Getting Started.