~/portfolio/blog — a_godot_game_that_patches_itself_over_bi
build: ok v0.4.7
← cd ../
guest@portfolio:~/blog$ cat 2025-10-self-patching-godot-torrent.md
2025.10.07

A Godot game that patches itself over BitTorrent

#godot · #bittorrent · #distribution ·10 min

A few days ago I downloaded a legal torrent inside a Godot game. Today I’m prototyping the next step: the game updating itself over BitTorrent, with no server, no Steam, no patcher service.

The piece that makes this work is a corner of the BitTorrent spec that almost nobody talks about: BEP 46 — mutable torrents.

The problem with shipping indie games

If you want to ship a Godot game today, your realistic options are:

  • Steam — 30% cut, takes a few weeks to get approved, controls your update channel.
  • itch.io — friendlier, but the butler CLI and itch app are the main update path, and discoverability is its own challenge.
  • Self-hosted download — you pay for bandwidth, you build the patcher, you handle CDN.
  • GOG / Epic — same trade-offs as Steam with smaller audiences.

There’s a fifth option that’s been hiding in plain sight for over a decade: Blizzard’s installer has used BitTorrent under the hood for years. Warcraft, Diablo, Overwatch — all delivered via swarms. The technology is battle-tested at planetary scale. The reason it isn’t common for indies is that nobody packaged it up.

What BitTorrent gives you for free

  • Bandwidth scales with your audience. Popular game equals faster downloads, not a bigger AWS bill.
  • Resilience. No single point of failure. If your website is down, the swarm keeps seeding.
  • Geography. Players near each other share to each other. No CDN edge configuration.
  • It already works in restrictive networks. The protocol is old and well-understood enough that it routes around most firewalls.

The cost has historically been trust — how do you know the torrent hasn’t been tampered with, and how do you push an update without making the old torrent obsolete?

Enter BEP 46: mutable torrents on the DHT

A normal torrent is content-addressed. The infohash is the SHA-1 of the file list. Change one byte, change the hash, you have a new torrent and old peers are now seeding the wrong thing.

BEP 46 fixes this by adding an indirection layer over the DHT. You generate an Ed25519 keypair. Your public key is what users subscribe to. To publish an update, you sign a new infohash with your private key and put it on the DHT. Anyone subscribed to your public key automatically discovers the new version.

The whole flow:

  1. Player installs the game. The installer drops the public key somewhere safe.
  2. On boot, the game queries the DHT for the latest signed pointer from that public key.
  3. If a newer infohash is found, fetch the metadata, diff against what’s on disk, download only the changed pieces.
  4. Verify every piece against the signed manifest. Swap files atomically.

That’s the entire update protocol. No server. No accounts. No infrastructure bill. Just a keypair and a DHT lookup.

The Godot piece

There’s a Godot torrent client in the works at godot-torrent. The addon already does the boring parts — leeching, seeding, piece verification. What I’m adding is:

  • BEP 46 publishing from inside the game binary
  • A CLI mode that lets the developer push an update with their private key
  • A boot-time check in the game runtime that looks for updates and applies them
# Conceptual API — not final
var publisher := MutableTorrentPublisher.new()
publisher.load_private_key("user://release.key")
publisher.publish("build/MyGame-v0.4.2/")
# Inside the game
var updater := MutableTorrentSubscriber.new()
updater.public_key = "<dev's published key>"
var update := await updater.check_for_update()
if update:
    await updater.apply(update)
    OS.restart()

Embedding the CLI in the game binary means the developer doesn’t need a separate publish pipeline. Build, sign, publish — three commands. The next time a player boots the game, they’re on the new version.

Things that will be hard

I’m not going to pretend this is solved. Real things that need answers:

  • First-run bootstrap. Pure DHT discovery can be slow on a cold cache. The installer probably needs to seed the initial public-key pointer from a known source.
  • Code signing on macOS and Windows. Replacing binaries on disk after the OS has notarized them is a fight. Likely the answer is shipping a separate updater process that has the entitlement to modify the bundle.
  • NAT traversal. uTP and hole-punching cover most cases, but not all. A fallback HTTP seeder is probably unavoidable.
  • Anti-cheat and competitive games. If the binary can change itself, the server has to be the authority on what version is valid. Single-player games don’t have this problem.

Why this matters

The economic model of indie distribution has been “give someone 30% forever so they handle the network problem.” BitTorrent has solved the network problem for two decades. BEP 46 finally solves the update problem on top of it. The only thing missing was a runtime that game developers actually use to bundle it up.

That runtime is Godot. That bundle is in progress. Watch this space.