How much do TCP and UDP headers differ in size, and what does that mean for battery-powered IoT devices? Let’s quantify the cost.
Header sizes:
- TCP header: 20 bytes minimum (no options)
- UDP header: 8 bytes
For a 10-byte sensor payload: \(\text{TCP packet} = 20\text{ (IP)} + 20\text{ (TCP)} + 10\text{ (data)} = 50\text{ bytes}\) \(\text{UDP packet} = 20\text{ (IP)} + 8\text{ (UDP)} + 10\text{ (data)} = 38\text{ bytes}\)
Overhead comparison: \(\text{TCP overhead} = \frac{40}{50} \times 100\% = 80\%\text{ is headers}\) \(\text{UDP overhead} = \frac{28}{38} \times 100\% = 73.7\%\text{ is headers}\)
But the real difference is connection setup:
TCP 3-way handshake for EVERY new connection:
- SYN: 20 (IP) + 20 (TCP, no data) = 40 bytes
- SYN-ACK: 40 bytes
- ACK: 40 bytes
\(\text{Total handshake} = 120\text{ bytes}\)
UDP has NO handshake: \(\text{Total setup} = 0\text{ bytes}\)
Full transmission cost (single message with new connection):
| TCP |
120 |
50 |
170 |
| UDP |
0 |
38 |
38 |
Energy calculation (LoRa radio at 120 mA TX current, SF7 at 125 kHz BW with ~5.5 kbps data rate):
- TCP: 170 bytes = 1,360 bits at 5,470 bps = ~249 ms airtime
- UDP: 38 bytes = 304 bits at 5,470 bps = ~56 ms airtime
\(\text{TCP energy} = 120\text{ mA} \times 0.249\text{ s} = 29.9\text{ mAs} = 0.0083\text{ mAh}\) \(\text{UDP energy} = 120\text{ mA} \times 0.056\text{ s} = 6.7\text{ mAs} = 0.0019\text{ mAh}\) \(\text{Savings} = \frac{0.0083 - 0.0019}{0.0083} \times 100\% = 77.1\%\)
At scale (1,000 sensors, 1 message/hour, 1 year = 8,760 hours):
- TCP with reconnect: \(0.0083 \times 8{,}760 \times 1{,}000 = 72{,}708\text{ mAh} = 72.7\text{ Ah}\)
- UDP: \(0.0019 \times 8{,}760 \times 1{,}000 = 16{,}644\text{ mAh} = 16.6\text{ Ah}\)
Battery life per sensor (2,000 mAh battery, 1 message/hour):
- TCP (reconnect each message): \(\frac{2{,}000}{0.0083 \times 24} \approx 10{,}040\text{ days} \approx 27.5\text{ years}\)
- UDP: \(\frac{2{,}000}{0.0019 \times 24} \approx 43{,}860\text{ days} \approx 120\text{ years}\)
Note: These theoretical values only account for TX energy. Real-world battery life is much shorter due to receive windows, sleep current, microcontroller processing, and battery self-discharge (typically 1-5 years for LoRa sensors).
With persistent TCP connection (1 handshake + keep-alives, 8,760 messages/year): \(\text{Per message} \approx 50\text{ bytes} + \text{periodic keep-alive overhead}\)
Key insight: UDP saves ~77% energy per message when TCP reconnects each time. With persistent TCP connections (as MQTT uses), the gap narrows significantly. For battery-powered IoT with sporadic transmissions, CoAP over UDP is more energy-efficient; for devices with stable connections, MQTT over TCP with persistent connections is viable.