ib_insync died overnight in March 2024 and everyone panicked.
If you're running production trading systems, you better figure out your options before shit hits the fan. Here's what actually happened with each Python API and why ib_async is the only sane choice left.
The Great ib_insync Death of 2024
Ewald de Wit died in March 2024 and took ib_insync with him.
His GitHub account shows the brutal truth: "✝2024" and all repos archived.
If you're still running ib_insync in production, it works fine until it doesn't
- then you're completely fucked.
The community scrambled to fork his work under ib-api-reloaded and created ib_async.
It's not just changing the name
- they actually fix bugs and release updates. The PyPI package gets regular updates instead of being frozen in time like a digital tombstone.
Your Three Options (Spoiler:
Two Are Pain)
Official ibapi: Where Dreams Go to Die
The official ibapi is what IB gives you.
It's a shitty Java port with callbacks everywhere. You'll spend 80% of your time debugging callback hell instead of making money. The [source code](https://github.com/Interactive
Brokers/tws-api) hasn't been meaningfully updated since Obama was president.
## This is your life with ibapi
- enjoy the misery
class IBApp(EWrapper, EClient):
def __init__(self):
EClient.__init__(self, self)
self.positions = []
def position(self, account, contract, position, avgCost):
# IB's callback system is trash
self.positions.append((contract.symbol, position))
def error(self, req
Id, errorCode, errorString, advancedOrderRejectJson):
# "Error handling" in ibapi means suffering
if errorCode == 2104:
pass # Market data farm died again
else:
print(f"Something broke: {errorCode}: {errorString}")
**ib_async:
The One That Doesn't Hate You**
ib_async is what ib_insync was before it died.
The docs are readable, examples actually run, and migrating is usually just changing your import. Your Jupyter notebooks work without mysterious hangs. I migrated in 30 minutes and it just... worked. Fucking miracle.
## This actually makes sense
from ib_async import *
util.start
Loop() # Magic line that makes Jupyter work
ib = IB()
ib.connect('127.0.0.1', 4001, clientId=1)
contract = Stock('AAPL', 'SMART', 'USD')
bars = ib.reqHistoricalData(contract, endDateTime='', durationStr='30 D',
barSizeSetting='1 day')
df = util.df(bars) # Pandas DataFrame without 50 lines of conversion code
ib_insync: The Walking Dead
Still works but it's dead. Archived since March 2024.
If you're terrified to touch working code, fine
- keep using it until IB changes something and breaks your shit. Then you'll be scrambling to migrate during a crisis instead of doing it calmly now.
Performance Numbers From My Actual VPS
Tested on a $20/month DigitalOcean droplet running real market data (not bullshit synthetic tests):
Memory Usage:
- ibapi: ~20MB (then you add your own async layer and hit 100MB)
- ib_async: ~60MB (includes the event loop you need anyway)
- ib_insync: ~55MB (perfect and frozen in time like a dead person)
Connection Reliability:
- ibapi:
You write reconnection logic (you'll fuck it up)
- ib_async: Handles reconnections without me losing my mind
- ib_insync:
Same as ib_async but dead code can't fix new bugs
Docker: Why I Hate My Life
Everyone wants to containerize trading apps.
Most fail because IB Gateway is a 2005 Java GUI that expects a desktop environment.
IB Gateway Docker Reality:
You need VNC to configure IB Gateway.
Docker's networking breaks with IB for mysterious reasons
- just use host networking and save 3 weeks of debugging. I tried bridge networking for a month before giving up.
## docker-compose.yml that actually works (after 3 weeks of pain)
version: '3'
services:
ibgateway:
image: your-ib-gateway:latest
network_mode: host # Gave up fighting Docker networking
ports:
- "4001:4001"
- "5900:5900" # VNC because IB Gateway is from the stone age
environment:
- DISPLAY=:1
Production Reality (The Shit They Don't Tell You):
- IB Gateway crashes daily
- plan for it
- Random disconnections will happen during volatile markets
- Memory leaks everywhere
- restart containers nightly
- Check positions on startup or wake up to surprises
The Migration That Doesn't Suck
If you're on ib_insync, migrating to ib_async is usually just changing imports:
## Change this shit
from ib_insync import *
## To this shit
from ib_async import *
## 95% of your code works unchanged
## The other 5% is event handler syntax bullshit
What actually breaks during migration:
- Event handlers might need tweaking (took me 10 minutes to fix)
- Some async patterns need refactoring (if you did weird stuff)
- IB Gateway bugs will still fuck you (not the library's fault)
When to Use What (Real Talk)
Use ib_async if:
- You want code that doesn't make you hate programming
- You develop in Jupyter (ib_async just works)
- You value sleep over microsecond optimizations
- You want bugs fixed instead of ignored
Use ibapi if:
- You're doing HFT and microseconds matter (spoiler: use C++ instead)
- You have masochistic senior engineers who love callback soup
- You enjoy 3am debugging sessions and hate weekends
Keep using ib_insync if:
- Your production code works and you're scared shitless to change it
- You're "planning to migrate next quarter" (sure you are)
- You like living with technical debt that will explode eventually