I got into World of Warcraft around 2005 and eventually found the private-server scene. The idea that you could run your own version of the game was fascinating: not just play it, but move NPCs, change quests, alter rates, script encounters and generally mess with a world you controlled.

I wasn’t trying to become a software engineer. I just wanted to understand how the game worked. It ended up teaching me a huge amount because everything I learned was attached to a real problem, and eventually around 800 players were very good at telling me when I’d got something wrong.

It started with the database

A huge amount of the game world lived in MySQL: creature spawns, quests, items, loot, game objects and plenty more. SQL was the easiest place to start changing things without having to understand the enormous C++ codebase underneath it.

Projects like MaNGOS and the Unified Database project, usually just UDB, were brilliant for that because everything was there to inspect. I’d change something, break it, work out why and gradually understand more of how the pieces fitted together.

Eventually the database wasn’t enough. Some behaviour lived in the server itself, which meant getting into C++.

My C++ was not good

I was definitely not some teenage C++ prodigy. My C++ was rough. A lot of what I did involved reading existing code, copying patterns, changing things and working under people who knew considerably more than I did.

But instead of isolated exercises, I was trying to understand a huge application simulating an MMO world. If I wanted something to behave differently, I had to find the code responsible and understand enough around it to make the change.

Lua appeared for the same reason: some behaviour and encounters were scripted. Without really deciding to, I’d gone from changing MySQL rows to working with SQL, C++, Lua and a large open-source codebase because each one was the next thing standing between me and what I wanted to make work.

At the time I didn’t think of any of this as software engineering. I just wanted the boss fight to work.

Version control came with the projects

The emulator scene was also where I learned version control: Subversion, then Mercurial, then Git. The projects moved, so I moved with them.

It mattered because upstream changes were landing constantly while we had our own modifications on top. We needed to know what revision we were running, which patches we’d applied and whether an update was worth taking. We also contributed some quest fixes back upstream, which was my first experience of fixing something locally and sending the fix back because the problem existed for everyone.

The scene also introduced me to another part of open source: everyone eventually falls out with everyone else. MaNGOS forked, TrinityCore came out of that world, database projects split, repositories moved and different groups maintained different versions of roughly the same thing.

At the time it mostly felt like annoying project drama. Looking back, it was my first lesson that software projects are made of people, and people can change the direction of a project just as dramatically as the code can.

Then our private server got quite big

At its peak our server had around 800 players online at once. What started as me messing around with World of Warcraft had turned into a login server, a web server, two realm servers, a dedicated database server and basic monitoring, which I’m fairly sure was Cacti.

A gameplay and PvP montage made by some of the players on the server back then.

Once things were spread across multiple machines, guessing stopped being useful. Was MySQL struggling? Was one realm under more load? Was it the network? Was the realm process itself falling over? We needed some idea of what the system was actually doing.

The emulator cores were impressive, but sustained player counts had a habit of exposing their limits. We applied custom ACE networking patches to help under higher concurrency and were careful about which core revisions we deployed because stability mattered more than being current.

Even then, if a realm ran long enough under load, eventually it would fall over. So we restarted them every night at around 4am.

Hardly anyone is online at 4am, the realm is probably going to die eventually anyway, so restart it before it gets the chance.

It wasn’t elegant, but it worked.

The players were the best test suite we had. Something could work perfectly for us and fall apart once hundreds of people were using it. They found broken quests, weird behaviour, performance problems and assumptions we’d never thought to question.

There wasn’t much room for pretending something worked because it worked on your machine. If the players couldn’t use it, it was broken.

I wrote bad SQL, misunderstood C++, deployed things that behaved differently from what I expected and watched assumptions collapse under real load. Sometimes 800 people collectively demonstrated that I had been talking complete shit.

That feedback loop taught me more than any tutorial could have. Something could work with fifty players and fall over with five hundred. You could stare at application code for hours and eventually discover the database or network was the actual problem.

PHP happened because we needed a website

PHP arrived for exactly the same reason as everything else: the server needed a website.

Players needed somewhere to register and we wanted pages that could interact with account and server data, so I started building them. There is a fairly direct line from writing questionable PHP for a private WoW server to eventually getting paid to build software professionally, which is still slightly ridiculous when I think about it.

There was never really a curriculum. I learned SQL because the world data lived in MySQL, some C++ because the database stopped being enough, Lua because encounters were scripted, PHP because we needed a website, and infrastructure because the player count kept growing.

The technologies mattered because they were standing between me and something I wanted to make work.

It was probably my first real production system

I didn’t realise it at the time, but that private server was probably the first complicated software system I had any meaningful responsibility for. There was application code, a database, multiple servers, networking, monitoring, deployments, upstream dependencies, custom patches, other developers and a lot of real users.

I made loads of mistakes, which is probably why I learned so much. I had to change things, run them and deal with whatever happened afterwards. Sometimes that meant fixing something I’d broken. Sometimes it meant accepting that the sensible solution was a 4am restart script and moving on with your life.

Twenty years later, the work still feels strangely similar. The languages are different and there are fewer angry World of Warcraft players involved, but I’m still usually looking at a system that isn’t behaving the way I expect and trying to work out which part is actually responsible.

Looking back, I have really fond memories of that period. It was messy and occasionally chaotic, but it was also the thing that lit the fuse. I had no idea where any of it would lead at the time, but so much of what came afterwards started there: writing code because I wanted something to work, digging into systems I didn’t understand yet and getting completely hooked on figuring them out.

I didn’t know I was learning software engineering. I thought I was running a World of Warcraft server.