Deep Engineering #45: Francesco Ciulla on Building Production Systems in Rust Without the Expensive Rewrite
Memory safety, the borrow checker as your most patient teacher, and how to introduce Rust without the disruptive migration project that puts teams off
View the latest HubSpot Developer Platform updates in Spring Spotlight
See what’s new for the HubSpot Developer Platform!
Ship faster with AI coding tools like Cursor, Claude Code, and Codex. Build MCP-powered AI connectors, run serverless functions with support for UI extensions, and use date-based versioning to streamline roadmap planning.
✍️ From the editor’s desk,
Welcome to the 45th issue of Deep Engineering!
The TIOBE Index for April 2026 puts Rust at number 16, up from 18 last year. While the community widely expected it to break into the top 10, that momentum has slowed. TIOBE attributes this to adoption friction, noting that broader mainstream uptake has proven harder to achieve than the language’s early trajectory suggested.
The institutional picture, however, tells a different story. The NSA and CISA issued joint guidance in June 2025 urging organisations to adopt memory-safe languages for national security systems and critical infrastructure. Google’s Android security team reported that memory safety vulnerabilities, which accounted for 76% of Android bugs in 2019, fell below 20% for the first time in 2025 after the team prioritised writing new code in memory-safe languages.
The Linux kernel maintainers also made Rust permanent, making it a core part of the kernel. The argument about whether memory-safe systems programming languages belong in production is settled at the institutional level. The harder argument, therefore, is how engineering teams adopt it without the expensive, disruptive projects that give the language an undeserved reputation for being hard to introduce.
Francesco Ciulla, author of The Rust Programming Handbook and head of developer relations at Zerops, directly challenges that perception. His framework starts not with the language’s strengths but with the one service in your system where Rust would make an undeniable, measurable difference. That is what this issue covers.
Let’s get started.
Architecting Production-Ready APIs for Agents
Most API ecosystems were not built for autonomous agent usage. This hands-on masterclass covers governed API design, OpenAPI specifications, and multi-API workflow modelling with Arazzo so your platform stays predictable and safe under automated usage.
2 FOR 1 deal is also live. Bring a colleague free and learn how to design AI-ready, governed APIs
Use code DEEPENG50 for 50% off.
Expert Insights
Rust Does Not Need to Replace Your Stack to Make It Better
by Saqib Jan with Francesco Ciulla
Every engineering team that considers Rust tends to circle the same concerns. The language is difficult to learn, expensive to adopt, and more practically useful to systems programmers than to the teams building and running services at scale.
Francesco Ciulla, author of The Rust Programming Handbook, Docker Captain and head of developer relations at Zerops, says, "I've heard that conversation many times, and my response has always been that the framing is wrong from the start."
Ciulla has been building with Rust since 2022, has spoken about it internationally at conferences, and his perspective on Rust adoption is shaped less by enthusiasm for the language and more by a practitioner’s view of where it actually earns its place in a production system. That starting point matters, he says, because the teams that struggle with Rust adoption tend to start from the wrong question.
A joke that contains a kernel of truth
People in the Rust community have long joked about rewriting everything in Rust, and the memes around it have become something of a cultural shorthand for over-enthusiastic adoption. Like most good jokes, Ciulla acknowledges, it contains a kernel of truth. But the practical lesson is the opposite of what it implies. “The best way to introduce Rust in a big project is to find that hard part that is slowing things down, the bottleneck of all your services, and try to write one single service in Rust.” The rewrite everything instinct is how adoption projects become expensive and difficult to justify. The bottleneck-first instinct is how teams get a proof of concept that demonstrates real value before committing to anything broader.
The practical implication is that the adoption decision is not a language decision at the organizational level. It is an engineering decision at the service level. The question is not whether the organization should adopt Rust. The question is whether there is one service in the system that is slow, resource-intensive, or difficult to keep stable, where the properties Rust offers would make a measurable difference. If that service exists, it is the right place to start. If it does not, the case for introducing Rust at all is weaker than it might appear.
Ciulla’s production experience makes this concrete. Running a Rust web server on his own machine, he shared during our conversation that it used four megabytes of RAM in development and five in production. On a one-gigabyte droplet, that means more than 200 services running simultaneously in idle. That number is the kind of resource profile that changes what is economically viable to deploy, and it is the kind of argument that lands differently with an ops team than a language comparison ever could.
Flat latency is a real engineering argument
One of the most underappreciated technical arguments for Rust in production systems is not about speed in the raw throughput sense. It is about predictability. Languages that rely on garbage collection, including Go, Java, and Node.js, introduce periodic pauses when the collector runs. Those pauses can last hundreds of milliseconds. An HTTP request that arrives during a GC cycle experiences higher latency than one that does not. The user on the receiving end did not do anything differently. They were just unlucky.
Ciulla is candid about what this means in practice. “By not having a garbage collector on the back end side, you basically have flat latency. You don’t rely on luck, or on the user not being the unlucky one. It’s a problem that is removed.” For most web applications running at moderate scale, this distinction is invisible. For services with strict latency requirements, high concurrency, or SLAs that depend on consistent tail latency rather than average response time, it is one of the more significant architectural arguments available.
This connects to a broader point about where Rust earns its place and where it does not. The resource efficiency and latency predictability are not arguments for using Rust everywhere. They are arguments for using Rust in the specific services where those properties matter. A service that scrapes a website once a month does not need flat latency. A service handling a million concurrent users does. Knowing the difference is what separates a good adoption strategy from an expensive experiment.
Rust, when it is the wrong choice
Ciulla is honest about the cases where Rust is not the right tool, which is part of what makes his advocacy for it credible. If a team needs something simple and the deadline is tomorrow, Rust is probably the wrong choice. If a developer needs a working API by the end of the day and has no Rust experience, this is not the moment to start learning the language under delivery pressure. “When you need something simple, and you’re familiar already with Java or JavaScript, why don’t you use it?” The question is not rhetorical. It is the right question to ask before any technology adoption decision.
The ecosystem argument is also honest. Python has better libraries for data science. JavaScript has a larger package ecosystem for certain kinds of web work. Rust integrates well with other languages, but if what a team needs is native to another ecosystem, that is a real constraint rather than a preference. Good engineers use the right tool for the problem. The case for Rust is strongest when the problem involves performance, memory efficiency, or concurrency at a level where other languages start showing their limits.
The shepherd principle
One of the more practical observations Ciulla makes about organizational adoption is about knowledge rather than tooling. The bottleneck to Rust adoption at scale is rarely the language itself. It is whether the organization has someone who knows it deeply enough to validate the work being done in it. He draws the parallel to Docker adoption at the European Space Agency, where he worked and observed the tool move slowly not because of anything wrong with Docker, but because it was not well understood internally. The technology is never the problem, he points out. The knowledge is.
“You need the validation of an expert,” Ciulla says. In the era of AI-accelerated development, this point is sharper than it has ever been. Teams can now generate Rust code with AI assistance far faster than their ability to validate it has grown. That gap between generation speed and validation depth is where production incidents come from. Having at least one engineer on the team who understands the ownership model, the borrow checker, and the concurrency primitives well enough to review what the AI produces is not a nice-to-have. It is the thing that determines whether the Rust service is a genuine improvement or a liability waiting to surface.
Concurrency without the trauma
Most engineers who have worked with concurrency in Java or C++ carry a specific kind of wariness about it. The mental model for concurrency in older languages is that it is an advanced topic requiring extra care, specialized libraries, and a heightened awareness of race conditions and deadlocks. Ciulla describes learning concurrency in Java at university as the final, difficult session of the course, something treated as inherently dangerous and saved for the end of the degree.
His first attempt at a concurrency example in Rust produced the opposite experience. “When I had to teach concurrency in Rust in a YouTube video, I made an example in three minutes. I was done. I say okay, the basic example really lasted like two or three minutes because you just declare a couple of threads and literally done.” That experience reflects something structural about how Rust was designed. The language was created after multi-core processors were already standard. Concurrency was not retrofitted onto a model designed for single-threaded execution. It was built in from the start, and the ownership system that prevents data races at compile time is the same ownership system that governs memory safety everywhere else in the language. There is no separate concurrency model to learn. The properties that make Rust memory safe are the same properties that make concurrent code safe.
For teams building services that need to use available CPU resources efficiently, this is not a minor ergonomic improvement. It means that the gap between writing concurrent code and writing correct concurrent code is substantially smaller in Rust than in the languages most engineers have used before. The cost of concurrency, measured in debugging time and production incidents rather than lines of code, is genuinely lower.
The compiler is the most patient teacher on your team
The reputation Rust has for being difficult to learn is real, and Ciulla does not dismiss it. But his explanation for where the difficulty actually comes from is different from the common framing. The problem is not that the concepts are inherently harder than those in other languages. It is that Rust forces you to unlearn patterns that other languages allowed. Engineers who have spent years in C++ or JavaScript carry assumptions about how memory works, how mutability is managed, and what the runtime will silently fix for them. Rust does not fix those things silently. It surfaces them at compile time and requires you to address them explicitly before the code runs.
That shift in where the pain lands is the key insight. “Rust is not hard to learn,” Ciulla says. “It’s different. And this is how we should advocate for it.” The difficulty is front-loaded by design, because the language makes a deliberate trade of more friction during development in exchange for fewer failures in production. Teams that have spent significant time debugging null pointer exceptions, race conditions, or memory leaks in production understand this trade intuitively. The hours lost to a null pointer exception in production dwarf the hours spent fighting the borrow checker upfront.
The Rust compiler, which is the primary source of that upfront friction, is also the primary teaching tool the language provides. Error messages in Rust are unusually detailed and specific. They do not just tell you that something is wrong. They explain what rule was violated, show the relevant code, and often suggest a fix. Ciulla describes the compiler as a teacher rather than a gatekeeper, one that overcommunicates in the same way a good mentor does. “The errors in Rust are basically tutorials. They are helping you to write better code.” For teams introducing Rust to engineers who have not used it before, this property matters practically. The compiler is doing a significant part of the knowledge transfer work that would otherwise fall on the senior Rust engineer on the team.
Rust in the Linux kernel is paying off
The decision by the Linux kernel maintainers to not only allow Rust in the kernel but to plan for components that require it going forward is the kind of institutional endorsement the language community has been waiting for. Ciulla frames it clearly. Even if the experiment had failed, just the fact that Rust was considered a viable option for kernel-level work would have been a meaningful milestone. The language was competing in a domain that had been exclusively C and C++ territory for decades, and it earned a permanent place there.
For engineering leaders tracking where the industry is moving, this matters beyond the kernel itself. Government systems, military applications, and other security-critical domains are beginning to treat Rust as a default rather than an experiment. “Rust is slowly getting adopted at bigger and bigger levels,” Ciulla says. The adoption curve is not linear, but the direction is consistent. Teams that build internal expertise now are not chasing a trend. They are positioning ahead of a transition that is already underway in the most demanding environments in the industry.
The ecosystem argument is changing
One of the historically valid objections to Rust for web development was tooling maturity. Two years ago, Ciulla would not have committed to shipping a production SaaS product in Rust. Today he would, and the reason is specific rather than general. The Axum framework has matured to the point where it is a production-grade choice for web APIs, and the broader ecosystem around async Rust has improved substantially. “In 2026, I will use it,” he says of building a paid product with Rust as the backend, dropping the qualification he would have applied even a year earlier.
The toolchain story is also one of Rust’s genuine advantages for teams evaluating the full cost of adoption. Cargo handles dependency management, building, testing, and documentation in a single integrated tool. There is no equivalent of the npm versus yarn versus pnpm decision that teams arriving to JavaScript have to navigate before writing a single line of code. Running tests is cargo test. The integration is native to the language, not an ecosystem of competing choices layered on top of it. For teams that have spent time debugging JavaScript build configurations, this is not a small thing.
Rust in the AI accelerated development era
Ciulla makes an argument about Rust and AI that is worth sitting with. The claim is not that Rust is better for writing AI applications, though he has views on that too. The claim is that Rust may be one of the best languages to work in during the current period of AI-assisted development, specifically because of what it requires from the engineer reviewing AI-generated code.
When AI writes Rust code, the engineer validating it still has to understand ownership, borrowing, and the type system well enough to know whether the generated code is correct. The compiler will catch a large category of errors, but the human reviewer still needs to understand why the compiler is happy with a piece of code before shipping it. “If you have no control, either you are useless or you cause a problem. So in both cases, it’s not a good time for you.” That discipline, the requirement to understand what the code actually does rather than just accepting output that compiles, is not a burden unique to Rust. But it is more explicitly enforced by the language than in most alternatives, and that enforcement is valuable at a moment when the volume of AI-generated code is increasing faster than the average team’s ability to review it carefully.
🛠️ Tool of the Week
wrkflw — open-source tool for validating and running GitHub Actions locally
wrkflw lets you validate and execute GitHub Actions workflows on your local machine before pushing, catching configuration errors and pipeline failures before they reach CI. Version 0.8.0 shipped this week. Built in Rust.
Validates GitHub Actions workflow syntax locally before pushing to CI
Runs multi-step jobs and matrix builds without cloud dependency
Fast startup and low resource overhead from Rust’s binary compilation model
Catches pipeline failures early, reducing the feedback loop between code and CI
📎 Tech Briefs
Linux 7.0 ships with Rust as an official core kernel language - Rust loses its experimental tag in Linux 7.0, reaching full parity with C for kernel development after the Linux Kernel Maintainers Summit decision in December 2025.
Rust 1.95.0 released - The latest stable release introduces
cfg_select!, a compile-time macro for conditional configuration, and removes unstable support for custom target specifications on stable toolchains.crates.io opens new Svelte-based frontend for public testing - The Rust team invites the community to test the rebuilt crates.io frontend ahead of the planned production migration.
Cargo stabilises build.warnings configuration - The build.warnings field is now stable, giving teams a standardised way to configure compiler warning behaviour across workspace builds.
Zed 1.0 ships - The Rust-built code editor reaches stable release with GPU-accelerated rendering, real-time collaborative editing, Git integration, and native AI assistant support across macOS, Windows, and Linux.
That’s all for today. Thank you for reading this issue of Deep Engineering.
We’ll be back next week with more expert-led content.
Stay awesome,
Saqib Jan
Editor-in-Chief, Deep Engineering
If your company is interested in reaching an audience of senior developers, software engineers, and technical decision-makers, you may want to advertise with us.
Thanks for reading Packt Deep Engineering! Subscribe for free to receive new posts and help grow our work.






