One Thread Pulled Another
"I wanted dark mode. I rebuilt the whole thing."
For everyone. No engineering background needed.
On February 7th, 2026, a player named AnszaKalltiern opened a bug report. EVEMon — the character planning tool that EVE Online pilots had relied on for twenty years — was crashing. Not for everyone. Just for players with a lot of characters.
Around sixty characters, the app would freeze during startup and die with a "schedule conflict" error.
I'd forked EVEMon a month earlier to do basic maintenance. Update it to .NET 8, fix some socket issues, keep it alive. I wasn't planning to rebuild anything. I was just trying to help.
That crash report changed everything.
01What EVEMon Is
If you don't play EVE Online, here's the short version: it's a space game where your characters train skills in real time — even while you're offline. A skill might take five minutes or five months. Serious players run dozens of characters across multiple accounts, each with their own training queue, wallet, assets, and skill plans.
EVEMon was the tool that tracked all of it. First released in August 2006 by a player named Six Anari, it was maintained by fifty-seven contributors across two decades. Nearly ten thousand commits. EVE University listed it in two separate categories — Character Monitoring and Skill Planning — the only tool with that distinction out of 120+ listed.
Peter Han kept it alive through 2021, migrating it to CCP's new ESI API system across twenty releases. His last commit was March 17, 2021. After that: silence. Nineteen hundred days of it.
The app still worked. Mostly. For most people. But it was a Windows-only application built on a framework from 2002, and nobody was improving it.
02The Crash
Ansza had around seventy characters. When they tried to load them all, EVEMon would get to about sixty and crash. The error pointed to a "schedule conflict" — the internal system that decided when to fetch data from CCP's servers was choking.
I started investigating. What I found wasn't a simple bug. It was a cascade of problems that had been hiding for years, invisible as long as nobody pushed the app past fifty characters.
The scheduler — the part of the app that fetches character data from CCP's API — was built on a Windows timer that fired every five seconds. Every tick, it would check every character, every endpoint, and fire off requests. With sixty characters and a dozen data types each, that's 720 checks every five seconds. All on the same thread that draws the screen.
The app wasn't crashing because of a bug. It was crashing because the foundation couldn't handle the load. The architecture had a ceiling, and Ansza had hit it.
03What I Found Underneath
Once I started pulling at the scheduler thread, I found more threads:
The scheduler was tangled into a central object called EveMonClient that had sixty-nine static events. Every screen in the app, every data update, every timer tick — all of them communicated through this single object. It was like an entire office building with one telephone line.
That object couldn't be fixed without separating the business logic from the screen-drawing code. But the business logic was mixed into the Windows-specific code across sixty-six files. You literally could not test the skill calculations without launching a Windows application.
And you couldn't modernize the screen-drawing framework — which would have given the app dark mode, Linux support, and macOS support — without first untangling all of the above.
One thread pulled another. Then another. Then another.
04The Decision
Dark paint on a 2006 architecture. Ship fast. Hope nothing breaks.
Fix the foundation. Get dark mode + Linux + Mac for free. Invest 7 weeks.
I had two choices:
Patch the symptom. Add a delay to the scheduler so it doesn't choke at sixty characters. Ship it. Move on. The app would still be Windows-only, still be a single massive project with no test coverage, still have that ceiling — just a slightly higher one.
Fix the foundation. Separate the architecture into layers. Replace the communication system. Rebuild the scheduler. Write tests. Then replace the entire screen-drawing framework with something modern. Get dark mode, Linux, macOS, and the ability to handle hundreds of characters — not as features bolted on, but as natural consequences of a sound architecture.
I chose the second option. That decision would consume the next twelve weeks and turn a maintenance fork into a complete application rebuild.
05The Cascade
Here's how it unfolded:
- The crash revealed the scheduler was fundamentally broken — 930 polls per second on the UI thread.
- Fixing the scheduler required decoupling it from the sixty-nine static events on the god object.
- Decoupling the events required splitting the single monolithic project into separate assemblies.
- Splitting the project required separating business logic from the Windows screen-drawing code.
- Separating the code made the entire application testable for the first time.
- With tests in place, the scheduler could be rewritten from scratch with proper rate limiting.
- With a clean architecture, the screen-drawing framework could be replaced entirely.
- The new framework gave us dark mode, six themes, and cross-platform support — for free.
Eighty-four days. From a crash report to a stable release running on Windows, macOS, and Linux with 1,800 tests and support for 100+ characters.
Dark mode — the thing I originally wanted when I first looked at EVEMon months before any of this — came as a side effect. Not as a goal, but as a consequence of fixing the real problem.
06What I Am
I should be transparent about something. I'm not a developer by training. I don't have a computer science degree. I'm an EVE Online player who uses Claude Code — an AI coding assistant — to direct work on codebases. I can read code, understand architecture, make decisions about what needs to change and why. The actual line-by-line implementation was done in collaboration with AI.
Some people will have opinions about that. I think the results speak for themselves: the application works, the tests pass, the architecture is sound, and the community is using it daily.
07What's Coming
In the next part, I'll show you exactly what I found when I opened the hood on the codebase. The numbers are real — 210,002 lines of code, 18,072 lines of dead code talking to services that no longer exist, and 23 tests for a codebase that now has 1,800. It's a forensic look at what twenty years of maintenance mode does to software, and it explains why every thread had to be pulled.