About four months ago, I started a new job, and we made a decision to rebuild our platform (for reasons not directly related to this article). I initially went with Java for the backend.
It was a safe choice. Our developers knew it. It’s fast, well supported, and has libraries for pretty much everything. It wouldn’t have been a bad decision.
Then one of our principal engineers asked: “Why not Rust?”
My reaction, almost immediately, was: “Duh, of course!”
I knew of Rust, but I didn’t know the language. It simply hadn’t been on my radar. I was still thinking primarily about which language our developers already knew. That question made me reconsider the choice in the context of how we were going to build in a AI software factory paradigm.
I read up on Rust to confirm my initial gut feel, and the more I learned, the more sense it made. We’ve now been using it for about a month and a half, and it’s looking amazing. We’re still early in development, so these are early impressions. But I wanted to share what changed my thinking. Maybe “Why not Rust?” is a useful question for you too.
Performance matters at scale
Rust offers native performance and direct control over memory without a garbage collector. Performance is a major reason to consider it.
Java is already pretty damn fast, and the comparison depends on the workload. But in high-traffic business systems, even modest efficiency gains can have meaningful economics. If you can squeeze out another 10% of performance (an example, not a known benchmark) that can reduce compute requirements when CPU work drives your costs. At scale, those gains matter.
Types and generics that enforce contracts
What has impressed me most in development is how much the compiler can enforce.
In a Python project, we built harness checks to stop agents from replacing another module’s private state or using computed attribute names to bypass static checks. But Python sits at the dynamic end of the spectrum, so that’s an easy comparison. How does Rust compare with Java?
Java already provides strong typing, generics, and compiler-enforced access control. Rust extends those contracts to how resources may be borrowed, mutated, and shared across threads. Two examples from our platform make that concrete.
A transaction handle can’t escape the operation that owns it. Our data-access API lends application code a transaction context for the duration of its work. Rust’s lifetime rules prevent that borrowed context from being returned or retained for later use. Participating queries also require exclusive mutable access to it. The compiler checks these restrictions before the code runs; equivalent lifetime restrictions in Java generally depend on API design and runtime checks.
Async work must be safe to move between threads. An agent can write code that looks reasonable locally but captures something unsuitable for a multithreaded runtime. Our transaction API expresses this requirement through a Send bound. If its async work holds a single-threaded shared pointer across an await, compilation fails. This doesn’t solve every concurrency problem, but it catches mistakes that ordinary Java compilation permits.
These requirements live in generic bounds and function signatures. They let us describe more than which values a function accepts and returns: we can also constrain how its implementation uses resources. That’s particularly valuable when AI is writing the implementation.
Macros for consistent behavior
Rust provides a supported way to transform code during compilation. Attribute macros can rewrite an annotated function, adding cross-cutting behavior before the resulting code goes through type and borrow checking.
An illustrative policy API could look like this:
#[public_interface(authenticated = false)]
pub fn foo(name: &str) -> String
#[endpoint(authenticated = true, required_role = "admin")]
pub fn bar(name: &str) -> StringThese declarations can add cross-cutting concerns (authentication, authorization, observability, auditing, etc) to business logic. The checks execute at runtime; their integration with the function is checked during compilation.
Other languages can achieve similar behavior. Python decorators apply transformations at runtime. Java’s standard annotation processors generate additional files; rewriting existing methods requires other tooling. Rust makes that transformation a supported part of its normal compilation process.
For AI development, that’s a useful combination: concise declarations backed by generated implementations that must satisfy Rust’s compiler.
A few other benefits
There’s one interesting (though somewhat fringe) benefit. Rust is the language of WebAssembly. Demanding browser workloads can use Rust compiled to WASM. Additionally native clients (MacOS, Windows) with an embedded runtime can load modules containing shared business logic. That offers a way to reuse selected implementations across environments.
Finally, Rust has an active community, good documentation, and a substantial ecosystem. Those aren’t benefits per se, but they matter when choosing a language to build a platform around.
What are the trade-offs?
Rust can be demanding to learn. Ownership, borrowing, lifetime relationships, and generic constraints make Rust code pretty dense and hard to read.
However, working in a software factory environment changes how well you need to know the language. You still need to understand Rust conceptually: how it handles memory, concurrency, and types. Polyglot developers will recognize many of the underlying ideas, even if Rust expresses them differently. But you can work effectively without ever becoming fluent at writing Rust yourself.
What you do need is what I call scanning: reading a signature to understand its contract, and looking through a function to understand its general behavior. You don’t have to untangle every implementation detail as your normal way of working. AI can help explain unfamiliar syntax and navigate complicated types, while you go deeper where the behavior needs closer examination.
Long builds remain a cost. AI doesn’t remove the time spent compiling generated code, specializing generics, and optimizing the result. There are established practices for reducing build times, so this is a manageable engineering concern, but it remains part of the trade-off. The mitigation techniques are outside this post’s scope.
Six weeks in, I’m happy our principal engineer asked the question. Rust’s performance and enforceable contracts were already attractive. With AI handling the implementation, I believe the one remaining trade-off is totally worth it!


