Once latency and throughput are separate dials, you start noticing how many techniques turn one by deliberately turning the other the wrong way.
Batching
Batching is the one you will meet first. Writing a thousand database rows one statement at a time pays the per-statement overhead a thousand times. One bulk write pays it once and can move fifty times as many rows a second. The cost lands on the first row, which now waits for its 999 companions.
Message producers do the same trick, holding a batch open for a few milliseconds to fill it. More messages per second, and every individual message arrives a little later. For an analytics pipeline that trade is obviously right. For a fraud check holding up a checkout it is obviously wrong.
The real failure is making the trade without noticing, because that is the real failure. A client library that quietly buffers writes underneath a latency-sensitive endpoint has made the decision for you, and your metrics may not show it.
Parallelism and queues
Parallelism looks like a free win, and Amdahl's Law says how far it goes: your speedup is capped by whatever fraction of the work stays sequential. Parallelise 95 percent of a job perfectly and the remaining 5 percent still holds you to twenty times faster, however many machines you rent. Fanning out has its own tax, since the response waits for the slowest branch, which is the tail latency problem arriving again.
Queues are the third lever. Put one in front of a worker pool and you absorb bursts far above what you sustain, then smooth them out. That is a win for throughput and for staying up. Time spent in that queue is still latency, and it is invisible in your service's own metrics because the clock starts when work is picked up. Measure from the moment a job is enqueued, or your dashboards will insist everything is fine while people wait.
Worked example
Nadia owns an ingestion service at an ad-tech firm that writes click events to Postgres, its relational database, one row at a time: 2,000 rows per second at 3 ms each, and the service falls behind every evening peak of 6,000 per second. She adds a buffer that flushes every 50 ms or 500 rows, whichever comes first, using multi-row INSERTs. Throughput jumps to 30,000 rows per second on the same hardware, and the backlog problem disappears. Each event now waits up to 50 ms before hitting disk, which nobody downstream can even perceive for analytics data. Six months later a teammate reuses the same buffered writer for a payment audit log with a hard 100 ms end-to-end budget, and the 50 ms flush interval quietly eats half of it. Same code, same trade, opposite verdict.