In networking for professional embedded systems, the choice of transport is not just about theoretical speed or maximum throughput. It impacts handshake time, packet loss resilience, channel security, field problem diagnosis, and, most importantly, how the software will evolve over the product lifecycle.
Yet QUIC is often described in an oversimplified way: as the protocol that will "replace TCP and UDP". In reality, the question is more interesting and more useful for those who design gateways, embedded Linux and connected IoT devices. QUIC doesn't eliminate UDP: it uses it as a basis. And, in many modern scenarios, it takes the place of the TCP + TLS combination, adding multiple streams, built-in encryption, and faster connection times.
For this reason, talking about QUIC in embedded systems does not mean following a web trend. It means understanding when this transport architecture brings real value and when, instead, TCP or UDP remain more suitable, simpler and more robust solutions with respect to the application context.
The Real Nature of QUIC in Embedded Systems
One of the most dangerous simplifications is to treat QUIC as a simple "faster than TCP" protocol. In reality, QUIC is a modern transport built on top of UDP and designed to directly integrate capabilities that in the traditional stack were distributed across multiple layers: security, stream multiplexing, connection management, and faster resumption mechanisms.
For those developing embedded products, this changes the architectural reasoning. You are no longer choosing just between “reliable protocol” and “lightweight protocol,” but between different transport models, with different trade-offs. QUIC is particularly interesting when the device needs to talk to cloud services, HTTPS APIs, web dashboards or remote backends, and when connection opening latency or multiplexing of simultaneous requests have a real impact on system behavior.
The key point is therefore this: QUIC should not be read as an absolute alternative to everything else, but as a design tool to be used where its additional complexity produces a measurable advantage.
Practical example: Check if an embedded endpoint responds in HTTP/3 with curl
Before thinking about the theory, it is worth checking if your endpoint really exposes HTTP/3 over QUIC:
# Test di un endpoint HTTPS con tentativo HTTP/3
curl --http3 -I https://gateway.example.com/api/health
# Output atteso (semplificato)
HTTP/3 200
server: nginx
alt-svc: h3=":443"; ma=86400
Explanation: If the server and client negotiate HTTP/3 correctly, you are already using QUIC in the application path. It's a quick way to figure out if your embedded Linux platform, reverse proxy, or cloud service is truly exposing the new transport stack, rather than sticking with traditional HTTPS over TCP.
Why QUIC Really Matters to Embedded Projects
QUIC becomes relevant in embedded systems when the device is not a simple node that sends a few bytes of telemetry every now and then, but a more advanced network element: an industrial gateway, an edge computer, a custom router, a local web UI, a bridge between LAN and cloud or an appliance that exposes modern APIs.
In these contexts, the potential benefits are real. The first is the faster connection setup, especially in reconnections. The second is the presence of multiple independent streams in the same connection, useful when the same endpoint must serve concurrent requests without the classic global blocking effect. The third is the tight integration with the HTTP/3 model, which makes QUIC particularly natural when the product already speaks HTTP to browsers, apps or remote services.
Translated into product terms, QUIC makes sense when you want to improve responsiveness, mobility, security by design and application parallelism without building everything by hand on top of UDP or without being tied to the operational limitations of the classic TCP + TLS model.
Practical example: multiple independent streams on a single QUIC connection
One of the most important conceptual advantages is the separation between application streams:
/* Pseudocodice: stessa connessione QUIC, stream separati */
quic_conn_t *conn = quic_connect("cloud.example.com", 443);
quic_stream_t *telemetry = quic_open_bidi_stream(conn);
quic_stream_t *logs = quic_open_bidi_stream(conn);
quic_stream_t *config = quic_open_bidi_stream(conn);
quic_send(telemetry, temp_payload, temp_len);
quic_send(logs, diag_payload, diag_len);
quic_send(config, cfg_payload, cfg_len);
Explanation: Packet loss that impacts one stream does not automatically block other streams as happens more easily when multiple application flows are rigidly supported by a single TCP connection. For a gateway that needs to serve telemetry, diagnostics and configuration simultaneously, this difference can become very real.
QUIC Does Not Replace UDP and Does Not Make TCP Obsolete
Here lies the most common misconception. QUIC does not replace UDP at the underlying layer, because it is encapsulated in UDP. This allows it to cross much of the existing network infrastructure without requiring a new native IP protocol and, at the same time, to bring an important part of the transport logic into user space.
But this doesn't mean that UDP will disappear or that TCP will become useless. Instead, it means that QUIC occupies a different space. In cases where you need reliable transport, built-in security, and multiple streams, QUIC can practically replace TCP + TLS. In cases where you want maximum application control over datagrams, very tight latencies or minimal complexity, UDP remains very strong. In cases where you want the most established, observable, and universally supported solution, TCP continues to be an excellent choice.
The real architectural question is therefore not "Is QUIC better?". The correct question is: "does my application really benefit from the QUIC model more than what you pay for in complexity, footprint and debugging?"
Practical example: Quick comparison between QUIC, TCP and UDP in an embedded project
| Transport | When it makes sense | Strong points | Main limitations |
|---|---|---|---|
| TCP | Classic APIs, reliable backends, mature tooling | Very high compatibility, simple debugging, consolidated stack | Heavier handshake, less efficient multiplexing |
| UDP | Datagrams, real-time streaming, lightweight custom protocols | Minimal overhead, total control on the application side | No built-in reliability or security |
| QUIC | HTTP/3, embedded Linux gateway, edge cloud, modern APIs | Built-in TLS, multiple streams, faster reconnections | Greater complexity, less immediate observability |
Explanation: QUIC is not the "new default" for every embedded project. It is a strong choice in a specific range of systems: those rich enough to support a more advanced stack and connected enough to derive real benefit from it.
Handshake, Multiple Streams and 0-RTT: Where QUIC Really Changes the Rules
Much of QUIC's value emerges in three specific areas. The first is the communication startup time, because the protocol integrates security more tightly than the TCP model followed by TLS. The second is stream multiplexing, which allows multiple independent logical streams to be transported in the same connection. The third is support for 0-RTT in reconnections, which can further reduce perceived latency when the application context allows it.
But here we need planning discipline. 0-RTT is not a "free boost": it can introduce replay risks if used superficially. Furthermore, having multiple streams does not automatically eliminate all backpressure or flow control problems: it just means that the protocol offers better primitives, not that the application architecture becomes correct on its own.
In serious embedded systems, these features should therefore be read not as marketing slogans, but as options to be used wisely where they really improve the behavior of the product.
Practical example: Enabling HTTP/3 on an embedded Linux gateway with NGINX
A realistic case is an embedded Linux gateway that exposes a local web UI or API to the cloud:
server {
listen 443 ssl;
listen 443 quic reuseport;
server_name gateway.example.com;
ssl_certificate /etc/nginx/certs/fullchain.pem;
ssl_certificate_key /etc/nginx/certs/privkey.pem;
ssl_protocols TLSv1.3;
ssl_early_data on;
add_header Alt-Svc 'h3=":443"; ma=86400';
location /api/ {
proxy_pass http://127.0.0.1:8080;
}
}
Explanation: In this scheme NGINX publishes the same service in both traditional HTTPS and QUIC/HTTP/3 modes, leaving the negotiation up to the client. It is a pragmatic approach because it allows QUIC to be introduced without breaking compatibility with clients or networks that do not support it.
QUIC in Embedded Linux Systems: Where It Makes the Most Sense
QUIC's natural territory, in the embedded field, is not the minimum microcontroller with a few tens of free kilobytes. It is the embedded Linux system with full connectivity, structured user space, certificates, reverse proxy, updated TLS stack and the need to communicate with modern browsers, backends and APIs.
Here QUIC can become an advantage for at least three product categories. The first is the gateway that exposes a web UI or remote API. The second is the edge device that must support multiple concurrent exchanges with the cloud without continuously opening and closing connections. The third is the system that must manage mobility, network changes or non-ideal conditions without paying the full cost of a new application session each time.
In other words, QUIC in embedded is primarily a technology from embedded Linux, connected appliances, and edge computing, not a one-size-fits-all answer for everything a microcontroller contains.
Practical example: Test a client build with HTTP/3 support
When you port QUIC to a custom platform, the first obstacle is often not the application but the toolchain:
# Verifica rapida del supporto nella toolchain
curl -V
# Esempio di output atteso (semplificato)
curl 8.x.x ...
Protocols: http https
Features: alt-svc HTTP3 ...
Explanation: On many embedded Linux platforms HTTP/3 support is not "free". It should be checked in the curl build, in the TLS library used, in the linked QUIC libraries and in the proxy or frontend server. This is one reason why QUIC is an architectural theme, not a simple configuration flag.
The Real Limits of QUIC in Production
A common mistake is to assume that QUIC automatically improves every connection. It's not like that. Precisely because it uses UDP as a basis, QUIC also inherits some less obvious operational constraints when thinking only about the ideal protocol: more aggressive timeouts along the path, shorter NAT bindings, the need to keep the connection alive or resume it in a controlled way, and above all the possibility that some networks block UDP traffic entirely.
This aspect is crucial in products distributed in the field. If your device needs to work in enterprise environments, filtered networks, mobile hotspots, industrial infrastructure, or end-customer installations that you don't directly control, you can't design QUIC as if it were guaranteed everywhere. You must provide for fallback, telemetry and controlled degradation.
Furthermore, using overly aggressive keep-alives can have a real cost on power-constrained devices. If your node is running on battery power or severe power profiles, keeping a QUIC connection alive just to avoid timing out may be worse than reopening it when needed.
Practical example: application-side transport fallback strategy
typedef enum {
TRANSPORT_QUIC,
TRANSPORT_TLS_TCP
} transport_t;
transport_t select_transport(network_caps_t caps) {
if (caps.udp_blocked)
return TRANSPORT_TLS_TCP;
if (!caps.http3_supported)
return TRANSPORT_TLS_TCP;
return TRANSPORT_QUIC;
}
Explanation: Fallback is not a minor detail. It is an integral part of the architecture. A robust system doesn't assume QUIC is always available: it uses it when it's convenient and explicitly falls back to TLS/TCP when the network or client doesn't allow it.
QUIC Datagram and Real-Time Traffic: Opportunities and Misunderstandings
Another little-discussed point is that the QUIC ecosystem is not limited to trusted streams. There is also an extension for unreliable datagrams over a QUIC connection, useful in scenarios where you want to maintain connection context but don't want the full retransmission semantics typical of reliable transport.
However, this does not mean that QUIC automatically becomes the best solution for all real-time traffic. In some cases, using pure UDP remains the most straightforward and readable choice. In others, QUIC datagrams can be interesting because they allow you to stay in the same ecosystem of authentication, encryption and session management.
The key is to avoid dogma. Not everything that goes over QUIC automatically becomes simpler or more efficient. It must be evaluated on a case-by-case basis, especially when the traffic has rigid constraints on latency, jitter or energy consumption.
Practical example: Separate reliable and unreliable traffic
/* Pseudocodice architetturale */
if (payload.type == PAYLOAD_CONFIG || payload.type == PAYLOAD_COMMAND)
quic_send_stream(conn, payload.data, payload.len); /* affidabile */
if (payload.type == PAYLOAD_VIDEO_HINT || payload.type == PAYLOAD_TELEMETRY_FAST)
quic_send_datagram(conn, payload.data, payload.len); /* non affidabile */
Explanation: This pattern only makes sense when the application truly benefits from having two different semantics in the same connection context. If your system doesn't have this need, adding complexity doesn't automatically bring value.
Observability, Debugging and Security: The Price of Modernity
QUIC brings with it clear benefits, but not for free. A significant portion of the protocol is encrypted, which profoundly changes the way network tools, middleboxes, and monitoring infrastructures can observe traffic. What with TCP was often immediately visible with packet capture, with QUIC requires a more mature telemetry and logging strategy.
This is especially important in professional embedded projects, where the problem is not just "does it work or not", but "how do I diagnose intermittent degradation in the fleet?". If you choose QUIC, you must also design together what will make the system behavior measurable: handshake metrics, fallback success rate, percentage of HTTP/3 traffic actually negotiated, app-ready timing, resume errors and network-side timeouts.
Security, however, is one of QUIC's strong points, but rigor is also needed here. For example, 0-RTT should only be enabled for operations that you can treat as replay-safe. Security doesn't come from the name of the protocol, but from the discipline with which you use it.
Practical example: track whether the gateway is really serving requests in HTTP/3
log_format quiclog '$remote_addr [$time_local] '
'"$request" $status $body_bytes_sent '
'proto=$server_protocol h3=$http3';
access_log /var/log/nginx/quic_access.log quiclog;
Explanation: In the lab it's easy to think you're testing QUIC when in reality much of the traffic continues to flow over HTTP/2 or HTTP/1.1. Inserting a marker in the logs allows you to measure the real percentage of requests served via HTTP/3 and to understand if the rollout of the new stack is working as expected.
When TCP or UDP Are Still the Best Choice
There are many embedded projects where introducing QUIC is not an evolution, but an unnecessary complication. If the device sends little data to a reliable backend, does not expose advanced web services and does not suffer from handshake or multiplexing times, TCP with TLS remains a very rational choice. However, if you are building a proprietary, very lightweight protocol with strict temporal logic or pure datagram traffic, UDP may remain unbeatable for simplicity and control.
The reality is that QUIC does not replace design reasoning. It makes it more sophisticated. For this reason, the decision should be made by looking at the platform, resource budget, client type, expected network quality, cost of debugging, and expected product life in the field.
In serious embedded systems, the right technology is not the newest one. It is the one that minimizes the overall technical risk throughout the life cycle of the product.
Practical example: rapid architectural choice rule
/* Regola pratica */
if (device_is_mcu_small && protocol_is_simple)
choose(UDP_or_TCP);
if (device_is_linux_gateway && serves_web_api && needs_modern_https_stack)
choose(QUIC_HTTP3);
if (fleet_operates_on_uncontrolled_networks && fallback_is_mandatory)
choose(QUIC_with_TLS_TCP_fallback);
Explanation: it is not an absolute formula, but a common sense rule. QUIC tends to perform best when the platform is rich enough to support it and when the product's usage model resembles that of modern web APIs, rather than that of minimal firmware.
QUIC As an Architecture Choice, Not as Fashion
Approaching QUIC as a simple networking option risks underestimating its real impact on the product. The choice of transport affects TLS stack, proxy, client, logging, fallback, observability, update strategy, and even how the fleet will be monitored in the years following release.
The most useful engineering principle therefore remains very simple: adopt QUIC only when you can really exploit its structural advantages. If your system doesn't benefit from HTTP/3, multiple streams, fast connection resumption, or network mobility, then the more modern solution may not be the best solution.
Conclusion
QUIC is not the protocol that retires TCP and UDP. It is a modern transport built on top of UDP that, in many scenarios, effectively replaces the TCP + TLS pair and becomes the foundation of HTTP/3. In embedded Linux systems, gateways and connected appliances it can represent a very real evolution. In small microcontrollers, minimal protocols, or systems where debugging and simplicity matter most of all, TCP and UDP often remain the more pragmatic choice.
As always in professional embeddedness, the difference is not the technology taken in abstract, but its coherence with the constraints of the product. QUIC makes sense when it truly reduces latency, application complexity, or operational risk. If, however, it is introduced only because "it is the future", it risks moving complexity into the stack without producing a measurable benefit in the field.
Consider whether QUIC really makes sense in your embedded system
Silicon LogiX supports you in the evaluation and integration of communication stacks for embedded systems and embedded Linux: from classic TCP/UDP architectures up to QUIC and HTTP/3 for gateways, edge devices and connected appliances. A technical approach, measurable and oriented towards operational robustness, not just protocol theory.
Request a network architecture consultation