Why Rust for Antifragile Systems
Memory safety without garbage collection, correctness without compromise
The Problem
Building AI-powered systems that handle business-sensitive decisions requires absolute correctness. A single memory bug, a race condition, or an unhandled edge case can mean real money lost, real obligations created incorrectly, real compliance violations.
Traditional systems languages give you performance but demand constant vigilance against memory errors. Garbage-collected languages give you safety but take control away from you—and introduce unpredictable latency.
AI-assisted development changes the equation.
The old argument against Rust was the learning curve. "My team knows Python. Rust is too hard." But when AI writes 80% of your code, the learning curve flattens. You're reviewing and directing, not writing every line by hand.
This shifts the question from "can my team write Rust?" to "what guarantees do I want from my code?" And when business-critical systems are on the line, the answer is: all of them.
Interpreted languages grew from a reasonable premise: programmer convenience during exploration. But we're not exploring anymore. We're building systems that must be correct, performant, and maintainable for years. The convenience of skipping compilation doesn't offset the cost of runtime errors in production.
We needed a language that:
- Makes entire classes of bugs impossible at compile time
- Gives us control over memory without manual management
- Performs at the level required for real-time ML inference
- Eliminates the need for middle layers and external services that don't add real value
The question wasn't "should we use Rust?" It was "can we afford not to?"
Current Options
| Option | Pros | Cons |
|---|---|---|
| C++The incumbent systems language. Maximum control, maximum responsibility. |
|
|
| GoSimple, fast compilation, built for concurrency. |
|
|
| RustMemory safety guaranteed at compile time. Zero-cost abstractions. |
|
|
Future Outlook
Rust is eating systems programming. The Linux kernel now accepts Rust code. Microsoft is rewriting Windows components in Rust. Google is using Rust in Android and Chromium.
This isn't hype—it's recognition that memory safety bugs are responsible for ~70% of security vulnerabilities in systems code. Rust eliminates these bugs by construction, not convention.
The end of interpreted languages for business systems.
Python, Ruby, JavaScript on the server—these languages grew from a reasonable premise: programmer productivity during exploration. Compilation was slow, iteration was king, and correctness could wait.
That premise no longer holds:
- AI writes code faster than humans. The productivity gap between Python and Rust shrinks when you're not typing.
- Runtime errors are expensive. In business-sensitive systems, a TypeError in production isn't a learning opportunity—it's a compliance incident.
- Performance matters again. ML inference, real-time decisions, streaming data—interpreted languages hit walls that compiled languages don't.
For AI systems specifically, Rust's ecosystem is maturing rapidly:
- Burn brings native deep learning with multiple backends (CPU, GPU, WASM)
- Polars provides pandas-level ergonomics at 10-100x the speed
- Tokio enables async networking at scale
The trajectory is clear: Rust will be the default for new systems software. AI-assisted development removes the last major objection—the learning curve. Starting with Rust now means we're building on the future, not migrating to it later.
Our Decision
✓Why we chose this
- Compile-time memory safetyThe borrow checker catches use-after-free, double-free, null pointer dereferences, and data races before your code ever runs. These bugs simply cannot exist in safe Rust.
- Zero-cost abstractionsHigh-level constructs compile to the same machine code as hand-written low-level code. You don't pay for abstraction with performance.
- Fearless concurrencyThe ownership system prevents data races at compile time. You can write parallel code without fear of subtle race conditions.
- Excellent toolingCargo is the best package manager in systems programming. rustfmt, clippy, and rust-analyzer provide a modern development experience.
- Growing ML ecosystemBurn, Polars, and ndarray provide production-ready ML infrastructure. We're not waiting for the ecosystem—it's here.
×Trade-offs we accept
- Learning curve (diminishing)The borrow checker requires a mental model shift. But with AI-assisted development, you're reviewing generated code, not writing every line. The learning curve matters less when Claude writes idiomatic Rust.
- Compilation timesRust compilation is slower than Go. We mitigate this with incremental compilation, cargo-watch, and fast iteration cycles. The trade-off: bugs caught at compile time, not in production.
- Smaller talent pool (changing)Fewer developers know Rust than Python. But developers who understand correctness can direct AI to write Rust. The skill becomes reviewing and reasoning, not memorizing syntax.
Motivation
Converge handles business-sensitive decisions—creating obligations, authorizing actions, managing risk. In this domain, "mostly works" is unacceptable.
The death of the middle layer.
Traditional architectures accumulate layers: ORMs, caching services, message queues, API gateways. Each layer exists because the core language couldn't handle the job directly, or because "that's how we've always done it."
Rust lets us collapse these layers. We don't need a caching service when the language is fast enough. We don't need an external queue when Tokio channels are zero-copy. We don't need an ORM when SQL is explicit and type-checked.
AI-assisted development accelerates this. Rewriting a Python service in Rust used to be a months-long project. Now it's a directed conversation. The economics of "just use the existing service" no longer hold when replacement is cheap and the result is faster, safer, and simpler.
Rust's guarantees align perfectly with our values:
Correctness over convenience — The borrow checker is inconvenient. It's also correct. We'll take the friction.
Explicit over implicit — Rust forces you to handle errors, think about lifetimes, consider ownership. Nothing is hidden.
Deterministic over probabilistic — No garbage collector means no GC pauses. Latency is predictable.
The Rust ecosystem now includes everything we need:
- Axum for HTTP APIs
- Tonic for gRPC
- Burn for ML inference
- Polars for data processing
- Tokio for async runtime
We're not compromising on ecosystem to get safety. We're getting both.
Recommendation
For new business-sensitive systems: Use Rust. The learning curve objection is obsolete in the AI-assisted era. Direct Claude to write Rust; review for correctness.
For ML/AI systems: The Rust ML ecosystem is ready. Burn and Polars are production-grade. Stop reaching for Python by default.
For teams: The skill is no longer "can write Rust from scratch." It's "can review Rust, understand ownership, reason about lifetimes." This is learnable in weeks, not years.
For existing Python/Node services: Evaluate rewrite cost with AI assistance. A service that took 6 months to build might take 2 weeks to rewrite in Rust with AI help—and the result will be faster, safer, and require no runtime.
For middle layers: Question every external service. Do you need Redis, or is your language just slow? Do you need Kafka, or can Tokio channels suffice? Rust lets you collapse architecture.
At Converge, Rust is our core language. converge-core, converge-runtime, converge-analytics, converge-llm—all Rust. We haven't regretted it once.
Examples
use chrono::{DateTime, Utc};
use rust_decimal::Decimal;
/// An obligation that cannot be constructed in an invalid state
pub struct Obligation {
id: ObligationId,
amount: Decimal,
currency: Currency,
due_date: DateTime<Utc>,
status: ObligationStatus,
}
impl Obligation {
/// The only way to create an Obligation - validates all invariants
pub fn new(
amount: Decimal,
currency: Currency,
due_date: DateTime<Utc>,
) -> Result<Self, ObligationError> {
if amount <= Decimal::ZERO {
return Err(ObligationError::InvalidAmount);
}
if due_date <= Utc::now() {
return Err(ObligationError::PastDueDate);
}
Ok(Self {
id: ObligationId::generate(),
amount,
currency,
due_date,
status: ObligationStatus::Pending,
})
}
// No setters - state changes go through explicit methods
pub fn fulfill(&mut self) -> Result<(), ObligationError> {
match self.status {
ObligationStatus::Pending => {
self.status = ObligationStatus::Fulfilled;
Ok(())
}
_ => Err(ObligationError::InvalidStateTransition),
}
}
}Rust's type system enforces business rules at compile time. An Obligation cannot exist with invalid data, and state transitions are explicit. This isn't defensive programming—it's the only way the code can work.