Most of the time when you send data, you send it with a protocol that provides reliability. As part of this protocol, the other end has to send you back messages saying “I got that”. This happens over and over again and consumes a small amount of bandwidth.
In addition, if you download at the same time, your computer has to send back an “I got that” back to the server. That part competes with your upload.
TCP is a symmetric protocol that has built-in support for failures through re-transmissions. For every packet of data that has been sent to you from the server you are downloading from, it expects your computer to return an acknowledgment packet confirming that it has received that piece of data correctly. If it doesn’t, it will re-transmit it back to the client on the assumption that somewhere along the line, it was dropped before the client ever received it.
This acknowledgment can be piggybacked on data the client uploads back to the server. Still, in the case of HTTP downloads (or most large downloads), there is nothing to send back to the server once the download has started, so an “empty” packet with an acknowledgment in the header will usually be sent. So, to “download” a package, you must “upload” a packet to “download” the next. If you saturate your uplink and fill the outgoing buffer of the router full of data, then the packet you’re returning to the server will be stuck behind all this data. Most consumer connections are asymmetric (downloads are faster than uploads) as they work on the principle that most people will download far more than they upload. This is typically fine: You’re looking at around a 35:1 ratio in download packet size versus upload (acknowledgment) packet size, depending on the type of connection you’re using. For most relationships, such as ADSL, they are probably in the region of 3:1 to 10:1 for download: upload speeds.
This has the side effect that when your upload buffer fills, it will take longer to clear than anything in the buffer for downloads at the ISP side. This means your download link will download everything well before the uploads have finished causing your download link to pause as it waits for more data. You effectively reach a point of symmetry: One packet up means you can get one packet back down again and gives you the result you see when trying to download while you upload at the same time.
TCP does have a concept of a “window size.” This is the allowed amount of data that the server can send before it requires an acknowledgment from the client to enable it to send more. This can help in some situations, especially with smaller downloads, by allowing more data to be sent in one go. However, you are still limited by the returning acknowledgment packets for larger or longer downloads.
So long as one buffer is full (and this will typically be the upload buffer before the download one), the other side of the connection will be limited.
There are some tricks around this, such as smaller buffers (can slow down a connection, but make it more responsive), Quality of Service rules (to better prioritize packets being uploaded, re-arranging the order in the buffer to making larger upload packets wait behind smaller ones), or limiting the upload speed to below the limit to better manage barriers.
Unfortunately, most of these are not simple options and can have adverse effects on your connection if not accounted for or set up correctly, so it’s rare for most people not to be affected by this issue.