NEWS

Rustls turns 10 with benchmarks above OpenSSL, eyes version 1.0

The TLS library written in Rust outperforms OpenSSL and BoringSSL in handshakes per second and is preparing architecture changes in 0.24 ahead of the stable API.

Rustls turns 10 with benchmarks above OpenSSL, eyes version 1.0
Image: Redação iMasters

Rustls, a TLS library written in Rust and designed to be memory-safe, turned ten years old and published a retrospective with performance numbers and the roadmap toward its first stable API. Started in May 2016, it reached version 0.1.0 that same year and, a decade later, became the native Rust alternative to the ubiquitous OpenSSL, the same library whose C codebase carries a history of memory vulnerabilities (Heartbleed being the most remembered case).

For those who build and operate software in Brazil, this isn't a niche curiosity. TLS sits on the path of practically every HTTPS request that your application makes or receives. Swapping the cryptography stack for an implementation with memory safety guaranteed by the compiler has a direct impact on the attack surface of any service in production, and now it comes backed by numbers that put Rustls ahead in throughput and handshakes.

From garage project to funded foundation

Rustls started as a volunteer effort, driven by independent contributors like Brian Smith and Dirkjan Ochtman. What changed the game was sustained funding: the Prossimo initiative, from the Internet Security Research Group (ISRG, the same organization behind Let's Encrypt), Amazon Web Services, and third-party audits by Cure53 funded by the CNCF enabled full-time work.

That money translated into resources that matter to those with compliance requirements: FIPS certification, post-quantum cryptography, and Encrypted ClientHello entered the project thanks to dedicated maintainers. It also funded architecture refactoring and robustness work, things that rarely survive in a project maintained only by goodwill.

The benchmarks: Rustls ahead

The retrospective brings comparisons of Rustls 0.23.37 against OpenSSL 3.6.1 and BoringSSL on x86_64 architecture. The numbers are measured per core, which helps reason about cost in horizontally scaled environments.

| Metric (per core) | Rustls 0.23.37 | OpenSSL 3.6.1 | BoringSSL | |---|---|---|---| | Full handshakes/s | 2,357 | 1,713 (1.38x slower) | 1,302 (1.82x slower) | | Resumed handshakes/s | 7,249 | 3,780 (1.92x slower) | 5,687 (1.28x slower) | | Received throughput (MB/s) | 7,333 | 6,238 (1.18x slower) | 6,218 (1.18x slower) | | Sent throughput (MB/s) | 7,421 | 5,844 (1.27x slower) | 7,565 (1.02x faster) |

Rustls leads in three of the four metrics. The only point where it loses is sent throughput, where BoringSSL is marginally ahead (1.02x). The most significant advantage shows up in resumed handshakes, nearly double the speed of OpenSSL, which is relevant for services with a high volume of short-lived connections.

The practical detail: it topples the myth that memory safety charges a performance toll. Here the Rust implementation doesn't just match but surpasses established C libraries in most of the measured scenarios.

The API discipline of the 0.23 line

Part of Rustls's reputation comes from the stability of the 0.23 line, which sustained dozens of updates without breaking compatibility. In discussions on Reddit and Hacker News, adopters cited exactly this consistency as a sign of mature API management, something that anyone who has suffered a forced migration in a critical dependency knows how to value.

What's coming in 0.24

The next version promises architecture changes focused on performance and ecosystem integration:

  • External buffer via the TlsInputBuffer trait: instead of routing everything through the standard I/O traits, input goes through this mechanism and output is appended to user-supplied vectors. This enables in-place decryption and eliminates redundant memory copies.
  • Async support via session types: handshake states become sequentially modeled, allowing handshakes to run in blocking, async, or completion-based style, a relief for anyone working with async runtimes.
  • Split mode: a feature requested by the community back in 2019. Today a single connection object handles both sending and receiving. In split mode, post-handshake traffic is split into SendTraffic and ReceiveTraffic objects, both implementing Send. Because they can operate independently on different threads, with a low-contention internal back-channel, applications with full-duplex traffic can effectively double their throughput.
  • Decoupled crypto providers in separate crates (rustls-aws-lc-rs and rustls-ring), removing build-feature unification panics and allowing the global provider to be configured externally.

This last point deserves the attention of anyone who has already been burned by Cargo's feature system: feature unification across transitive dependencies tends to produce unexpected behavior, and decoupling the providers into dedicated crates addresses exactly that pain point.

The road to 1.0

After stabilizing 0.24, the maintainers plan to move toward a stable 1.0 API, designed for long-term maintenance. For Brazilian teams that avoid adopting a cryptography library still at 0.x for fear of breaking changes, this is the missing signal: Rustls is moving from being an early-adopter bet to becoming a candidate for a production dependency with stability guarantees.

What remains open is the timeline. The retrospective sets no dates for either 0.24 or 1.0, and the maturity of the ecosystem around bindings for other languages (Rustls already has a C interface via rustls-ffi) remains the bottleneck for those who want the memory-safety benefit without rewriting their entire application in Rust. For those already in the Rust ecosystem, however, the numbers and the roadmap make clear that switching away from OpenSSL is no longer a performance sacrifice.

Translated from the Brazilian Portuguese original · Read the original