Five years ago, Rust in finance meant a few high-frequency trading firms and an exotic choice in a sea of C++. Today it is the default language for new payment rails at three of Europe's biggest banks. Over the past eighteen months, the engineering teams behind three very different banking systems — a SEPA instant-payment processor in Frankfurt, an interbank settlement engine in Paris, and a high-volume FX matching system in London — have made the same bet. They have rewritten critical paths in Rust, cut tail latencies by more than eighty percent, and produced services whose memory footprints are a fraction of what the JVM gave them.
This is not the story of one heroic rewrite. It is the story of a slow drift in institutional preference, a few well-timed library releases, and a generation of banking engineers who grew up on Rust before they ever touched COBOL. We spoke with engineering leads at all three banks to understand what changed, what surprised them, and what still keeps them up at night.
Why Rust finally won the banking pitch
The pitch for Rust in finance used to be a tough sell. The language is famously difficult to learn, the borrow checker is unforgiving, and the financial industry is conservative for good reasons — a six-month outage in a payment system can move billions of dollars out of trust.
What changed between 2021 and 2025 was a combination of ecosystem and economics. Tokio matured into a runtime that could credibly replace Netty. The Rust async story stabilized around async fn in trait and the Tower middleware stack. Critically, AWS, Cloudflare, and the major cloud providers began shipping Rust in their default control planes — meaning that any bank adopting those services was effectively inheriting a Rust dependency tree whether it liked it or not. The risk of going against the grain became larger than the risk of going with it.
There was also a regulatory tailwind. The US National Security Agency's 2024 guidance explicitly recommended memory-safe languages for critical infrastructure, and the European Union's Digital Operational Resilience Act tightened the rules around software provenance. When auditors started asking, "What language is your matching engine written in?" a clean answer in a memory-safe language saved weeks of paperwork.
The deciding factor, though, was internal: hiring. Rust developers are scarce, but they are disproportionately well-trained, and the ones willing to work in finance tend to be unusually senior. The banks that won the bet did so by hiring a small core of these engineers and putting them on the most painful service in the stack.
Case study 1: a SEPA payment processor in Frankfurt
The first migration took place at a Frankfurt-headquartered Landesbank, where the team operates the real-time gross settlement gateway that connects the bank to TARGET2 and to the SEPA Instant Credit Transfer scheme. Until 2023, the gateway was a 600,000-line Java monolith running on eight-Xeon servers with 256 GB of RAM each. P99 latency under load was 47 milliseconds, and the team could not push it lower without a JVM GC pause that periodically spiked the tail to over a second.
The Rust replacement was written by a team of six engineers over fourteen months. It uses tokio-postgres to talk to the underlying settlement ledger, rdkafka to consume the inbound payment stream, and a custom-built HSM client backed by PKCS#11 to sign each SCT Inst message. The service runs as a single statically linked binary, deployed as a sidecar to the existing JVM gateway during the cutover.
The result: median latency dropped from 11 ms to 2.1 ms, and P99 dropped from 47 ms to 9 ms. Memory consumption fell from a 12 GB JVM heap to a 380 MB resident set. The team now runs three replicas on commodity hardware that previously struggled to host a single JVM instance.
Case study 2: an interbank settlement engine in Paris

The second case is a cooperative banking group headquartered in Paris, which operates the netting engine that reconciles obligations between its member institutions at end-of-day. Until recently the engine was a 1.2-million-line C++ application with a thin Java façade for the HTTP layer. It worked, but it had three known memory-safety CVEs open at any given time and a security review cycle that took six weeks per release.
The decision to move to Rust was driven less by performance than by the security team's veto. The security committee told the engineering organization that no new feature could ship until all three open issues were fixed. The team weighed the cost of patching versus the cost of rewriting the hot path, and the rewrite was cheaper.
The rewrite was scoped narrowly. The database stayed. The message bus stayed. The Java façade stayed for regulatory reporting. The team replaced only the netting engine itself — about 80,000 lines of C++ — with 22,000 lines of Rust. The result was an 86% reduction in static memory footprint, a 70% reduction in CPU usage during the nightly netting window, and the closure of all three outstanding CVEs. The Rust engine now compiles with -D unsafe-code forbidden and is reviewed by a single security engineer instead of a rotating committee.
Case study 3: a high-volume FX matching system in London
The third case is the most aggressive. A London-based tier-1 bank's FX electronic-trading desk operates a matching engine that handles spot, forward, and NDF flow across more than thirty currency pairs. The matching engine ran on a Java-based Disruptor-style architecture with a separate C++ price-formatter feeding the book. The bottleneck was the price-formatter: a single-threaded component that turned raw quote streams into book updates at the rate of 1.2 million messages per second per currency pair.
In late 2024 the desk stood up a parallel Rust implementation of the price-formatter. It uses crossbeam-channel for lock-free communication with the upstream quote handlers, serde_json for the wire format, and a custom fixed-point decimal type that avoids the imprecision that has bitten several FX desks in past decade. The first production cutover was for the EUR/USD pair in February 2025.
Results from the first six months of production: throughput on EUR/USD is up 41%, P99 latency is down 81%, and the price-formatter process now fits comfortably in 96 MB of RAM where the C++ version needed 1.4 GB. The team is migrating the remaining pairs and is on track to decommission the C++ price-formatter entirely by the end of 2026.
The migration playbook: strangling the Java monolith
None of these three banks did a big-bang rewrite. All three used a pattern that engineers in financial services call "strangling" — running the new Rust service in parallel with the old Java or C++ system and shifting traffic incrementally as confidence builds.
The standard playbook has five phases. First, the team identifies a service boundary where the new service can be deployed as a sidecar or proxy without changing the upstream call sites. Second, the new service is built against a shadow traffic mirror — production traffic is copied to it but its responses are discarded. Third, the new service is promoted to "active mirror" mode, where its response is logged but the original is still served. Fourth, traffic is shifted by percentage: 1%, 5%, 25%, 50%, 100%. Fifth, the old code is deleted, usually six to twelve months after the cutover is complete.
| Bank / team | Old stack | New Rust service | Latency before (P99) | Latency after (P99) | Memory footprint reduction |
|---|---|---|---|---|---|
| Frankfurt Landesbank | Java 17 + Netty + JVM GC | tokio runtime + rdkafka + PKCS#11 |
47 ms | 9 ms | 97% (12 GB → 380 MB) |
| Paris cooperative bank | C++ netting + Java façade | tokio + serde + -D unsafe-code |
220 ms (netting window) | 66 ms | 86% (1.8 GB → 250 MB) |
| London FX desk | Java Disruptor + C++ formatter | crossbeam-channel + custom fixed-point |
14 µs / msg | 2.6 µs / msg | 93% (1.4 GB → 96 MB) |
What makes the strangler pattern work in banking is the observability layer. Each of these banks built dual-write dashboards from day one — every response from the new service is compared bit-for-bit against the old service's response, with discrepancies surfaced in a Slack channel that the engineering lead watches in real time. Within the first three months of any cutover, the dual-write channel is the only thing standing between the bank and a regulatory incident.
Latency, throughput, and the memory-safety angle
The 80% latency reduction is the headline number, but the memory-safety angle is what made these projects bankable. Each of these projects was approved by a risk committee that does not, by tradition, care about nanoseconds — it cares about control failures.
Rust's ownership model eliminates an entire class of bugs at compile time: use-after-free, double-free, data races, iterator invalidation. In a Java system, the same guarantees are provided by the JVM, but at the cost of a garbage collector that periodically stops the world. In a C++ system, the guarantees are provided by manual discipline, and the audit trail is a folder of code-review comments rather than a compiler diagnostic.
The combination is unique. With Rust, the bank gets JVM-level safety with C-level control over memory layout. There is no GC pause to tune, no -XX:+UseG1GC to debate, no off-heap allocation pattern to defend in code review. The code is safe by default, fast by default, and small by default.
The second-order effect is operational. When a Rust service crashes, it usually crashes because of a logic bug, not a memory bug. The post-mortem takes hours instead of weeks. When a security auditor asks for a Software Bill of Materials, the answer is cargo tree, printed in a second, with the entire transitive closure visible. None of this is unique to finance, but finance is the first industry where all of it has become table stakes for new infrastructure work.
The next frontier: Rust on the mainframes of finance
The next twelve months will be harder. The easy wins — greenfield payment processors, hot-path services in greenfield languages — are done. What remains is the long tail of mainframe-adjacent systems: the COBOL batch jobs that reconcile the general ledger at midnight, the PL/I risk engines that compute VaR across the trading book, the Assembler interfaces that talk to card-authorization switches.
Several of the banks in this story are now piloting Rust at the edge of these systems. One is using Rust to parse the output of legacy COBOL jobs and feed a modern analytics pipeline. Another is rewriting the message-format adapter between its settlement engine and SWIFT's MT/MX gateway in Rust, with plans to keep the legacy COBOL underneath. A third is experimenting with Rust on the IBM Z architecture, where the LLVM target is finally mature enough for production workloads.
The pattern is the same. The banks are not trying to eliminate COBOL. They are trying to put a Rust shell around it — a fast, safe, observable perimeter that translates between the world that exists and the world they want. Whether that perimeter is one service or a hundred, the language is the same.
For the moment, that language is Rust. The question is no longer whether memory safety is worth the engineering investment. It is how quickly the rest of the stack can catch up.
