Frequent TCP retransmissions mean packets are being resent because the sender didn't get an acknowledgment (ACK) in time, and to the application this shows up as added latency and sometimes intermittent errors. It points to something dropping or delaying packets between the two services, not necessarily a bug in either application's own code.
Root cause 1: network congestion or packet loss on the path (a saturated link, a lossy hop, a misbehaving switch or network interface). Validate with ping for baseline loss and jitter, a hop-by-hop tool like mtr to see which specific hop introduces loss, and OS-level retransmit and drop counters (ss -i or netstat -s for retransmission counts, ethtool -S for network-interface drop and error counters).
Root cause 2: receiver-side resource exhaustion, where the receiving host can't keep up with arriving traffic (for example because it's CPU-saturated or the application's read loop is slow). Be precise about the mechanism here, because two different things happen on a struggling receiver and only one of them produces retransmissions. If the application is slow to read but the kernel still accepts the packets, the receive buffer fills and the receiver advertises a zero window; the sender then stops sending and issues periodic window probes on a backing-off persist timer. That is a stall, not a retransmission: the data already in the buffer was acknowledged, and when the window reopens the sender sends new data rather than re-sending anything. It shows up in a capture as zero-window advertisements and probe packets, and in ss -i as a high rwnd_limited percentage, with the retransmission counter flat. Retransmissions come from the other half of receiver exhaustion: when the NIC ring buffer or the socket receive queue actually overflows, the kernel drops arriving segments before they are ever acknowledged, so the sender's retransmission timer fires. Validate by checking the receiver's CPU and load at the same timestamps as the retransmits, then look specifically for drop counters rather than window stats, netstat -s for socket buffer and backlog drops and pruned receive queues, ethtool -S for per-queue rx_dropped and ring overrun counters, alongside receive-window and buffer stats from ss -i and the receiving application's own read-loop latency. The practical decision rule: if you find a zero-window stall but no drops and no retransmits, the slow reader is real but it is not what is causing the retransmissions you were sent to explain, and you should keep looking at causes 1 and 3.
Root cause 3: a middlebox or MTU (maximum transmission unit) mismatch, for example a firewall silently dropping specific packet sizes, or a path-MTU issue where large packets never arrive intact. Validate with a packet capture (tcpdump, or Wireshark's retransmission filter) to see whether retransmits cluster around a specific packet size, and test the actual path MTU directly with a tool like tracepath.
Worked example: a tcpdump capture between the two services shows the exact same full-size segment being retransmitted repeatedly, a 1500-byte IP packet carrying the 1460-byte maximum segment size that a 1500-byte Ethernet MTU leaves after the 20-byte IP and 20-byte TCP headers, while smaller requests never retransmit. Running tracepath between the hosts shows a hop reporting a path MTU of 1400, well below the assumed 1500-byte Ethernet MTU, meaning a VPN or tunnel hop along the path is fragmenting or dropping the larger packets. Lowering the effective segment size (or fixing MTU discovery so it isn't blackholed) removes the retransmissions entirely.
Trade-offs and pitfalls: retransmissions alone don't tell you which of the three causes applies, you need a second correlated signal (loss location, receiver load, or packet-size pattern) to distinguish them. Jumping straight to "add more bandwidth" without confirming which cause is actually at play can spend money without fixing anything, a congestion-focused fix does nothing for an MTU blackhole.