Bali, Indonesia
Insights

BoringSSL vs OpenSSL 3.4 in Production Edge Gateways: Handshake Latency, Memory Footprints, and Post-Quantum Overhead

October 13, 2026
0:00
For teams operating ingress layers across Google Cloud, Microsoft Azure, and bare-metal edge environments, TLS termination is rarely treated as an application-layer concern until handshake latency spikes or container memory limits trigger out-of-memory (OOM) kills. Most Linux distributions still default to OpenSSL 3.x, carrying decades of legacy API baggage, dynamic cryptographic provider engines, and non-trivial memory allocations per SSL session context. Conversely, Google maintains BoringSSL specifically to strip legacy debt, prioritize concurrency, and serve as the core cryptographic engine for Chromium, Android, and GCP edge infrastructure. With hybrid post-quantum key exchange (specifically X25519 + ML-KEM-768) now mandated across high-assurance enterprise perimeters in late 2026, the computational and memory footprint of the underlying crypto library directly dictates gateway capacity. We compiled and benchmarked Envoy 1.32 and custom Nginx ingress builds against both BoringSSL (current master as of late 2026) and OpenSSL 3.4.0 under identical production workloads to determine whether the operational friction of maintaining a non-system library delivers measurable ROI.
The fundamental design philosophies of BoringSSL and OpenSSL create drastically different runtime profiles inside multi-threaded edge workers. OpenSSL 3.x introduced a complete architectural overhaul centered on the OSSL_PROVIDER framework. While this enables pluggable cryptographic modules (vital for legacy government FIPS implementations), it introduces severe abstraction overhead. Every symmetric cipher setup, digest allocation, and key exchange traversal in OpenSSL 3.x passes through provider lookup dispatch tables, reference-counted context lookups, and heap-allocated property queries. BoringSSL rejects this dynamic modularity entirely. It does not provide ABI stability across releases, disallows third-party dynamic engines, completely excises dead protocols (SSLv2, SSLv3, IDEA, SEED, and unauthenticated cipher suites), and hard-links optimized assembly directly into primitive calls. Thread safety inside BoringSSL relies on minimal lock contention, favoring atomic pointers and per-thread structures over the granular mutex locking found in OpenSSL ticket caches.
To simulate realistic multi-cloud edge termination, tests were deployed across identical GCP c3-standard-16 compute nodes (16 vCPU Intel Xeon 4th Gen Sapphire Rapids, 64 GB RAM) running Debian 13 (Linux kernel 6.12). Client load was generated from isolated Azure D16s_v5 instances within the same regional metro area over a low-latency interconnect. Load profiling was executed using h2load and wrk2, simulating 50,000 concurrent long-lived HTTP/2 streams interspersed with continuous new TLS 1.3 handshakes to stress the crypto state machine under CPU and memory pressure.
  1. Standard Classical TLS 1.3: ECDHE with X25519 key exchange, RSA-3072 and ECDSA P-256 server certificates, AES-128-GCM cipher suite.
  2. Hybrid Post-Quantum TLS 1.3: ML-KEM-768 combined with X25519 (X25519MLKEM768), simulating current compliance directives for transit encryption.
  3. Session Resumption Under Load: TLS 1.3 0-RTT and PSK ticket verification across a 4-worker multi-threaded proxy pool.
Below are the measured operational metrics under sustained load (50,000 concurrent sessions, 8,500 new TLS handshakes per second):
MetricOpenSSL 3.4.0 (Default Provider)BoringSSL (Commit 7b8e1f)Differential
Memory RSS (50k Idle TLS Sessions)1.84 GB612 MB-66.7% RSS
Memory per Active SSL Context~36.8 KB~12.2 KB-66.8% Heap
Classical Handshake P95 Latency12.4 ms7.8 ms-37.1%
Classical Handshake P99 Latency28.1 ms11.2 ms-60.1%
Hybrid PQ (ML-KEM-768) P95 Latency19.8 ms12.6 ms-36.4%
Hybrid PQ (ML-KEM-768) P99 Latency44.2 ms18.9 ms-57.2%
Max Handshake Throughput (Cores Saturated)9,420 handshakes/sec14,880 handshakes/sec+57.9%
CPU Lock Contention (perf mutex spin)8.4%under 0.5%Negligible
The most stark contrast appears in resident set size (RSS). OpenSSL 3.4 allocates deep cryptographic structures for certificate verification chains and provider lookups per connection context (SSL struct plus internal EVP_PKEY_CTX allocations). Under 50,000 active streams, the OpenSSL proxy consumed nearly 1.9 GB of RAM purely for state tracking. BoringSSL drastically compacts the SSL and SSL_SESSION structures. By stripping non-standard extensions and dynamic cipher metadata, BoringSSL maintained the same 50,000 active connection tables at roughly 612 MB. In Kubernetes environments running tight memory cgroups (for instance, Envoy sidecars limited to 1 GB), running OpenSSL under high concurrency routinely triggers cgroup OOM kills during handshake bursts, whereas BoringSSL operates safely within thresholds.
BASH
# Inspecting context allocations via jemalloc profiling during load
jeprof --show_bytes --pdf /usr/local/bin/envoy-boring profile.out > boring_alloc.pdf
jeprof --show_bytes --pdf /usr/local/bin/envoy-openssl profile.out > openssl_alloc.pdf
The allocation traces showed OpenSSL spending 24% of dynamic allocations inside OSSL_PROPERTY_LIST and dynamic provider name resolution tables, whereas BoringSSL showed zero heap allocations during the symmetric crypto phase once the handshake completed.
Deploying X25519MLKEM768 increases ClientHello and ServerHello packet sizes from approximately 500 bytes to over 1,500 bytes. This causes handshake payload fragmentation across TCP boundaries, increasing network packet round trips if the initial congestion window (initcwnd) is misconfigured. Cryptographically, ML-KEM encapsulation and decapsulation require significant polynomial multiplication cycles. BoringSSL leverages highly optimized AVX2 and AVX-512 assembly for ML-KEM-768 primitives on modern x86_64 cores. OpenSSL 3.4 relies on generic C implementations unless explicitly compiled with targeted compiler intrinsics that depend on system-level toolchain capabilities. Under sustained PQ handshake load, OpenSSL’s handshake P99 latency degraded to 44.2 ms due to thread synchronization locks during cipher context generation. BoringSSL capped P99 latency at 18.9 ms, maintaining consistent performance through lockless session ticket validation.
Envoy defaults to BoringSSL for its production builds. However, enterprises bound by specific corporate policy or OS-level package distribution often attempt to build Envoy using OPENSSL_3_SYSTEM toolchains. Here is how the build configurations diverge in production Bazel workflows.
BASH
# Standard hardened BoringSSL target inside Envoy's workspace
bazel build -c opt \
  --define boringssl=fips \
  --copt='-march=x86-64-v3' \
  --copt='-O3' \
  //source/exe:envoy-static
For custom edge proxies or internal utilities using CMake, linking BoringSSL statically prevents dynamic runtime dependency clashes:
CMAKE
# CMake snippet for statically linking BoringSSL
set(BORINGSSL_DIR '/opt/boringssl')

include_directories(${BORINGSSL_DIR}/include)

add_executable(edge_gateway main.cpp)

target_link_libraries(edge_gateway
    ${BORINGSSL_DIR}/build/ssl/libssl.a
    ${BORINGSSL_DIR}/build/crypto/libcrypto.a
    pthread
    m
)
To take advantage of BoringSSL’s hardware-accelerated hybrid post-quantum exchange in Envoy, define the curve preferences explicitly in the transport_socket configuration:
YAML
transport_socket:
  name: envoy.transport_sockets.tls
  typed_config:
    '@type': type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext
    common_tls_context:
      tls_params:
        tls_minimum_protocol_version: TLSv1_3
        tls_maximum_protocol_version: TLSv1_3
        # Prefer hybrid PQ first, falling back to standard X25519
        ecdh_curves:
          - X25519MLKEM768
          - X25519
          - P-256
      tls_certificates:
        - certificate_chain:
            filename: '/etc/ssl/certs/edge.bundle.crt'
          private_key:
            filename: '/etc/ssl/private/edge.key'
      session_ticket_keys:
        keys:
          - filename: '/etc/envoy/secrets/ticket.key'
When diagnosing high TLS termination latency in Linux production gateways, run perf to distinguish between network packet stalls and cryptographic lock contention.
BASH
# Capture call graph profile across all proxy worker threads for 30 seconds
perf record -F 99 -g -p $(pgrep -d',' -f envoy) -- sleep 30

# Analyze top cryptographic symbols
perf report --sort comm,dso,symbol --stdio
In an OpenSSL 3.4 deployment under load, the output routinely highlights contention in internal mutex code:
TEXT
# OpenSSL 3.4 Profile under contention:
18.42%  libcrypto.so.3  [.] ossl_property_query
 8.11%  libcrypto.so.3  [.] CRYPTO_THREAD_read_lock
 6.45%  libcrypto.so.3  [.] EVP_PKEY_CTX_new
 4.30%  libssl.so.3      [.] ssl_parse_clienthello_tlsext
Under BoringSSL, dynamic lookup entries vanish entirely, and CPU cycles correspond directly to cryptographic calculation:
TEXT
# BoringSSL Profile under identical load:
28.12%  envoy  [.] bssl::mlkem::Decapsulate
19.45%  envoy  [.] bssl::x25519_scalar_mult
12.30%  envoy  [.] aes_hw_ctr32_encrypt_blocks
 4.10%  envoy  [.] bssl::tls13_process_client_hello
Notice that CRYPTO_THREAD_read_lock does not appear in BoringSSL’s profile. Handshake dispatch routines access pre-compiled, static lookup tables without querying runtime providers.
BoringSSL is not a drop-in replacement for OpenSSL, and treating it as one introduces operational risk:
  1. No Stable ABI: BoringSSL makes no guarantees across git revisions. You cannot build a shared library .so once and rely on system package managers to update it. It must be built as a static dependency embedded directly into your gateway binary.
  2. Patch Management Overhead: Operating BoringSSL means you are responsible for monitoring the Google repository, tracking commits, and orchestrating full container rebuilds and rolling deployments whenever a vulnerability is remediated.
  3. FIPS 140 Certification Delays: BoringSSL does provide a validated FIPS module (BoringCrypto), but the certification lag is often longer and more inflexible than commercial or distribution-backed OpenSSL offerings (such as Red Hat Enterprise Linux's FIPS-validated OpenSSL builds).
  4. Missing Legacy APIs: BoringSSL intentionally omits engine mechanisms, legacy PKCS formats, and less-common cryptographic algorithms. If your upstream identity federation layer or enterprise SAML/WS-Trust pipeline depends on antiquated cryptography, BoringSSL will fail to build or run.
For enterprise edge gateways, containerized sidecars, and high-concurrency cloud proxies terminating over 5,000 handshakes per second, BoringSSL is the objectively superior technical choice. The 66% reduction in per-session memory consumption prevents catastrophic cgroup OOM failures, and its lockless internal architecture provides critical headroom when deploying resource-intensive Post-Quantum hybrid ciphers like ML-KEM-768. Reserve OpenSSL 3.4 for corporate infrastructure environments constrained by strict OS-level package maintenance policies, legacy protocol requirements, or environments where dynamic cryptographic provider integrations are mandatory. If you retain OpenSSL 3.4 at the edge, you must account for its memory footprint by allocating at least 40 KB of buffer RAM per expected concurrent connection and tuning thread pools to mitigate provider property lock contention.