TCP vs UDP — when to use each in embedded systems?
TCP provides reliable, ordered, byte-stream delivery. The kernel (or your embedded IP stack) handles retransmissions, duplicate detection, flow control, and congestion control. This reliability comes at a cost: each TCP connection maintains state (sequence numbers, timers, send/receive buffers consuming 2-16 KB of RAM each), and the three-way handshake adds latency to connection setup. TCP is the right choice when you need guaranteed delivery — firmware updates, configuration changes, log uploads, or any command-and-control channel where a lost message would cause incorrect behavior.
UDP provides unreliable, unordered datagrams — fire and forget. There is no connection state, no handshake, and minimal overhead (8-byte header vs TCP's 20-byte minimum). UDP is the right choice for time-sensitive data where freshness matters more than completeness — periodic sensor readings (if you miss one, the next reading arrives in a second), audio/video streaming (retransmitting a stale frame is worse than skipping it), and local service discovery (mDNS, SSDP). If you need reliability on top of UDP, you implement it yourself — protocols like DTLS, CoAP, and QUIC do exactly this.
In embedded systems, the tradeoff often comes down to RAM. A device with 64 KB of RAM supporting 50 simultaneous TCP connections would need 50 sets of send/receive buffers — potentially exceeding available memory. UDP connections are stateless and cost almost nothing. Many IoT protocols (CoAP, LwM2M) use UDP for this reason. However, MQTT — the most popular IoT protocol — runs over TCP because its QoS mechanisms are simpler when the transport already guarantees delivery. The choice depends on your specific constraints: available RAM, network reliability, latency requirements, and whether the application protocol already handles reliability.
Source: Networking Protocols Q&A
