{"id":28776,"date":"2026-01-17T23:07:10","date_gmt":"2026-01-17T22:07:10","guid":{"rendered":"https:\/\/daniel.haxx.se\/blog\/?p=28776"},"modified":"2026-01-18T16:24:31","modified_gmt":"2026-01-18T15:24:31","slug":"more-http-3-focus-one-backend-less","status":"publish","type":"post","link":"https:\/\/daniel.haxx.se\/blog\/2026\/01\/17\/more-http-3-focus-one-backend-less\/","title":{"rendered":"More HTTP\/3 focus, one backend less"},"content":{"rendered":"\n<p>In the curl project we have a long tradition of offering multiple optional backends for specific protocols. In this spirit we have added experimental support for a number of different HTTP\/3 + QUIC backends over time. A while ago we dropped one of those experiments, the <a href=\"https:\/\/daniel.haxx.se\/blog\/2025\/07\/29\/carving-out-msh3\/\" data-type=\"post\" data-id=\"27332\">msh3<\/a> backend.<\/p>\n\n\n\n<p><a href=\"https:\/\/github.com\/curl\/curl\/pull\/20226\">Today<\/a> we cleanup even more and <strong>remove support for yet another backend: the OpenSSL-QUIC stack<\/strong> and we are now down to only supporting two different HTTP\/3 alternatives: the ngtcp2 + nghttp3 combo or quiche. And out of those two, the quiche backend is still considered experimental.<\/p>\n\n\n\n<p>The first release shipping with this change will be curl 8.19.0.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">OpenSSL-QUIC<\/h2>\n\n\n\n<p>This is the QUIC stack implemented and provided by OpenSSL. To make matters a little complicated, this is a separate thing from the <em>QUIC API<\/em> that OpenSSL also offers. The first one is a full QUIC implementation, the second one is an API that is powerful enough to allow a separate QUIC implementation use OpenSSL for its cryptographic and TLS needs.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">A quick recap how history unfolded<\/h2>\n\n\n\n<p>2019 &#8211; BoringSSL introduced an API for QUIC. QUIC implementations picked it up and it worked. A pull request was made for OpenSSL to allow them to provide the same API so that QUIC stacks all over could use OpenSSL.<\/p>\n\n\n\n<p>2021 &#8211; OpenSSL eventually denied merging the pull-request and announced they would instead implement their own QUIC stack &#8211; that nobody had asked for.<\/p>\n\n\n\n<p>2023 &#8211; OpenSSL 3.2 shipped with support for their own QUIC stack. It was broken in many ways.<\/p>\n\n\n\n<p>2025: OpenSSL version 3.4.1 was released and now the QUIC stack worked <em>decently<\/em>. In OpenSSL 3.5.0 they announced a QUIC API that now finally allowed independent QUIC stacks to use OpenSSL.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Experimental<\/h2>\n\n\n\n<p>Skilled contributors added support for OpenSSL-QUIC to curl primarily to allow people using OpenSSL to still be able to use HTTP\/3.<\/p>\n\n\n\n<p>OpenSSL&#8217;s own QUIC implementation only reached <em>experimental<\/em> state in curl meaning that we explicitly and strongly discourage users from using it in production and reserve ourselves the right to change functionality and more between versions.<\/p>\n\n\n\n<p>There are three reasons why it did not graduate from experimental and they are also the reasons why we think we are better off without offering support for it:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>The API is lacking. We have communicated with the OpenSSL-QUIC team since even before the API first shipped and it still does not offer the knobs and controls we would like to make it a competitive QUIC alternative.  We don&#8217;t feel they care much.<\/li>\n\n\n\n<li>The performance is bad. And by bad I mean really bad. The leading QUIC implementation alternative ngtcp2 transfers data <em>much<\/em> faster in all benchmarks and comparisons. Sometimes up to <strong>a factor three<\/strong> difference.<\/li>\n\n\n\n<li>The memory use is abysmal. The amount of more memory required to do transfers with OpenSSL-QUIC compared to ngtcp2 can reach <strong>a factor<\/strong> <strong>twenty.<\/strong><\/li>\n<\/ol>\n\n\n\n<h2 class=\"wp-block-heading\">A drawing<\/h2>\n\n\n\n<p>This makes the curl backend situation simpler in the HTTP\/3 and QUIC department as the image below tries to show.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure data-wp-context=\"{&quot;imageId&quot;:&quot;69d6c78d2aff4&quot;}\" data-wp-interactive=\"core\/image\" data-wp-key=\"69d6c78d2aff4\" class=\"aligncenter size-full wp-lightbox-container\"><img loading=\"lazy\" decoding=\"async\" width=\"1920\" height=\"1080\" data-wp-class--hide=\"state.isContentHidden\" data-wp-class--show=\"state.isContentVisible\" data-wp-init=\"callbacks.setButtonStyles\" data-wp-on--click=\"actions.showLightbox\" data-wp-on--load=\"callbacks.setButtonStyles\" data-wp-on-window--resize=\"callbacks.setButtonStyles\" src=\"https:\/\/daniel.haxx.se\/blog\/wp-content\/uploads\/2026\/01\/curl-HTTP_3-backends9.jpg\" alt=\"\" class=\"wp-image-29027\"\/><button\n\t\t\tclass=\"lightbox-trigger\"\n\t\t\ttype=\"button\"\n\t\t\taria-haspopup=\"dialog\"\n\t\t\taria-label=\"Enlarge\"\n\t\t\tdata-wp-init=\"callbacks.initTriggerButton\"\n\t\t\tdata-wp-on--click=\"actions.showLightbox\"\n\t\t\tdata-wp-style--right=\"state.imageButtonRight\"\n\t\t\tdata-wp-style--top=\"state.imageButtonTop\"\n\t\t>\n\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"12\" height=\"12\" fill=\"none\" viewBox=\"0 0 12 12\">\n\t\t\t\t<path fill=\"#fff\" d=\"M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z\" \/>\n\t\t\t<\/svg>\n\t\t<\/button><figcaption class=\"wp-element-caption\">HTTP\/3 backends in curl in January 2026<\/figcaption><\/figure>\n<\/div>\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>In the curl project we have a long tradition of offering multiple optional backends for specific protocols. In this spirit we have added experimental support for a number of different HTTP\/3 + QUIC backends over time. A while ago we dropped one of those experiments, the msh3 backend. Today we cleanup even more and remove &hellip; <a href=\"https:\/\/daniel.haxx.se\/blog\/2026\/01\/17\/more-http-3-focus-one-backend-less\/\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">More HTTP\/3 focus, one backend less<\/span> <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":5,"featured_media":10108,"comment_status":"open","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[7],"tags":[33,436,193,414],"class_list":["post-28776","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-curl","tag-curl-and-libcurl","tag-http3","tag-openssl","tag-quic"],"_links":{"self":[{"href":"https:\/\/daniel.haxx.se\/blog\/wp-json\/wp\/v2\/posts\/28776","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/daniel.haxx.se\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/daniel.haxx.se\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/daniel.haxx.se\/blog\/wp-json\/wp\/v2\/users\/5"}],"replies":[{"embeddable":true,"href":"https:\/\/daniel.haxx.se\/blog\/wp-json\/wp\/v2\/comments?post=28776"}],"version-history":[{"count":14,"href":"https:\/\/daniel.haxx.se\/blog\/wp-json\/wp\/v2\/posts\/28776\/revisions"}],"predecessor-version":[{"id":29046,"href":"https:\/\/daniel.haxx.se\/blog\/wp-json\/wp\/v2\/posts\/28776\/revisions\/29046"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/daniel.haxx.se\/blog\/wp-json\/wp\/v2\/media\/10108"}],"wp:attachment":[{"href":"https:\/\/daniel.haxx.se\/blog\/wp-json\/wp\/v2\/media?parent=28776"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/daniel.haxx.se\/blog\/wp-json\/wp\/v2\/categories?post=28776"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/daniel.haxx.se\/blog\/wp-json\/wp\/v2\/tags?post=28776"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}