UDP datagrams
Design for loss and reordering
Test dropped, delayed, duplicated, and reordered datagrams before depending on UDP behavior.
10 minute lesson
UDP networks can lose, duplicate, or reorder messages. On loopback you’ll almost never see any of it, which makes loopback a dangerously polite test environment. Code that assumes delivery works fine in the lab and fails quietly in the field.
You can’t fix loss at the UDP layer. The application decides whether late data is useful and how much recovery is worth doing. A telemetry stream can shrug at 2% loss — the next reading supersedes the lost one anyway. A control command needs acknowledgment and retries. Neither answer is wrong; leaving the question unanswered is.
So make the lab hostile on purpose. Add a controlled random drop in the lab server:
if (Math.random() < 0.25) {
console.log('dropped for lab')
return
}
One in four requests now disappears, honestly logged so you can correlate.
Give messages sequence numbers so you can see what happened:
let seq = 0
setInterval(() => {
const message = JSON.stringify({ seq: seq++, sentAt: Date.now() })
socket.send(message, 41234, '127.0.0.1')
}, 200)
Send numbered messages with retry deadlines, using the request-ID machinery from the previous lesson. On the receiving side, track the highest seq seen and log anomalies:
if (message.seq <= highest) console.log('duplicate or out of order', message.seq)
Record duplicates and out-of-order arrivals over a few hundred messages. The drop code plus client retries will manufacture duplicates reliably. Reordering is rare on loopback, but real networks with multiple paths provide it, so the handling code must exist either way.
Then make the receiver’s behavior explicit, in writing:
lost: sender retries up to 3 times, 500 ms apart, then reports failure
duplicate: deduplicated by request ID
reordered: seq older than current state is discarded
Those three lines are the difference between a protocol and a hope. Any rule missing from that list gets defined later, by a production incident, at the worst possible time.
One boundary: do not use random fault injection in real traffic without a bounded experiment and approval. The drop snippet is for your lab server on loopback. In shared environments, injected failure is a change that needs the same review as any other.
Lesson completed