How BitTorrent's Choke Algorithm Works (And What I Learned Building Bad Peer)

Posted by Chaitanya Shahare on Tue, Jun 16, 2026

You know that one group project where two people did everything and three people collected the grade? That’s what early P2P networks looked like. Napster, Gnutella — studies found up to 70% of users sharing zero files. The people actually uploading got throttled into the ground, and the whole thing quietly died.

BitTorrent fixed this. The mechanism is called the choke algorithm, and after implementing it myself while building Bad Peer (a BitTorrent client I tuned to cut bandwidth waste ~40%), I think it’s one of the most underrated pieces of distributed systems design I’ve ever read.


The Setup

In a BitTorrent swarm, every peer both downloads and uploads. Your upload bandwidth is literally someone else’s download speed. The network lives or dies by how many people are willing to give back.

Nothing technically stops you from downloading at full speed while uploading nothing. The choke algorithm is BitTorrent’s answer to that problem — and it doesn’t need a server, a reputation system, or a trust score. Just local measurements, made every 10 seconds.


Choked vs Unchoked

Your client maintains connections to typically 50–80 peers. Most of them are choked — which just means you’ve told them “I’m not uploading to you right now.” Choke is your way of saying no.

Every 10 seconds, your client runs the algorithm. It looks at who’s been uploading to you the fastest over a rolling window. The top 3 (or 4) get unchoked — they get your upload bandwidth. Everyone else stays choked.

BitTorrent choke and unchoke network diagram

This is tit-for-tat. Give to the peers who give to you. Leechers who upload nothing get choked out of every peer’s unchoke slots. Their downloads crawl. Eventually the rational move is to start contributing.

The key detail: it’s local. You don’t check their global share ratio. You don’t ask a server. You only care what they’ve done for you in the last 10 seconds. Hard to game, cheap to compute.


The Bootstrap Problem (And How Optimistic Unchoking Fixes It)

Tit-for-tat has a catch: what about brand-new peers? They just joined the swarm. They have nothing to share yet. If everyone chokes them because they haven’t uploaded, they can’t download pieces, so they can’t start uploading. Total deadlock.

The fix is optimistic unchoking. Every 30 seconds, your client randomly picks one choked peer and unchokes them for free — no upload history required. This gives new peers a window to grab some pieces and enter the exchange loop.

It also serves as peer discovery. Your 3 unchoke slots might be full of good-enough peers, but there could be a way faster peer sitting choked. Optimistic rotation is how you find them.

Tit-for-tat cycle diagram showing 10s and 30s cycles


Rarest First: What You Download Matters Too

The choke algorithm handles who you upload to. There’s a parallel mechanism for what pieces you download: rarest first.

Your client tracks which pieces each peer in the swarm has. It always requests the rarest piece first — the one fewest peers are holding. If a peer has a rare piece and goes offline, that data could vanish from the swarm permanently. Spreading rare pieces fast is how you protect against that.

There’s a selfish angle too: if you have a rare piece, more peers want to connect to you. More connection requests means better candidates for your unchoke slots, which means faster downloads. The two systems reinforce each other in a way that feels almost designed, but emerged from simple rules.


What I Actually Found Building Bad Peer

When I built Bad Peer, my first cut was textbook: 10-second cycles, 3 unchoke slots, 30-second optimistic rotation. It worked fine, but I was burning bandwidth with nothing to show for it.

The problem was slot count interacting with piece transfer time. I was unchoking peers, they’d start exchanging, and then the cycle would fire again before the piece transfer finished. Peers would re-rank me, I’d drop off their list, and we’d both have wasted the bandwidth we already spent on an incomplete chunk.

Two changes fixed it:

  1. Reduced unchoke slots from 4 to 3 (tighter selection, less churn)
  2. Added hysteresis — a peer had to maintain their upload rate for two consecutive 10-second cycles before earning a slot

That killed the thrashing. Peers I unchoked stayed unchoked long enough for full piece exchanges to complete.

Result: ~40% reduction in wasted bandwidth with no loss in throughput. Same download speeds. Significantly less upload noise.

The spec gives you the skeleton. The real design is in the tuning.


Why This Is Actually Kind of Genius

No central server. No trust score. No blockchain. Just local measurements, made by selfish clients, every 10 seconds.

The emergent behavior is cooperative. Each peer acts in pure self-interest — upload to whoever uploads to me — and the swarm stays healthy because that’s exactly what health looks like at scale.

Decentralized systems don’t need trust. They need incentives that make cooperation the rational choice.

The choke algorithm is 20 years old, runs across billions of connections, and still holds up. If you want to understand how decentralized systems actually work — not just theoretically — build something that touches it.

You’ll get it in a way no spec ever gives you.