I’ve never really considered myself a traditional software developer, more a scripter.
I see a clear distinction there in terms of formal engineering knowledge and the end product produced — whether you’re designing deep software architectures or writing code to automate systems and solve operational problems. While I’m always keen to learn cleaner design patterns and better code structure, my primary focus has always been systems administration, network engineering, and cybersecurity. For me, coding was the practical vehicle to eliminate server headaches, secure infrastructure, and automate the repetitive work.
Looking back at how I got started as a teenager to where I am today, the tools and languages have shifted massively. But through all of it, one simple preference has never changed: the love of a clean, standalone, zero-dependency binary you can just drop on a machine and run.
From early batch loops and executable packers to clean, compiled Go binaries
Era 1: The Late 90s & Early 2000s — Batch Loops, Early Linux & Visual Basic
Back in my late teens, automation was scrappy as anything. I spent hours in front of a CRT monitor messing about with early Red Hat (which was insecure as anything back then!), early Debian, and Windows 98/2000 DOS prompts.
Most of my early scripts were DOS batch files — basic loops, conditional goto jumps, and automated file-sorting scripts for LAN parties:
@echo off
:loop
echo Checking network status...
ping -n 1 192.168.0.1 > nul
if errorlevel 1 goto alert
timeout /t 10 > nul
goto loop
:alert
echo [WARNING] Gateway unreachable!
goto loop
The Cybersecurity Connection: Why Compilers & Packers?
My obsession with turning scripts into standalone .exe files didn’t come from a textbook; it came from being in the underground IRC and cybersecurity scene.
Back then, malware authors and botnet operators were constantly using executable packers (like UPX) and batch-to-exe compilation tools to disguise bot droppers and obfuscate malicious scripts. While reverse-engineering and analyzing these incoming threats to defend networks, I quickly realised: “Hold on, I can use these exact same compiler tools to package my own admin utilities into neat, single-file executables.”
Alongside batch scripts, Visual Basic 6 was brilliant for this. Dragging a few buttons onto a form, wiring up simple COM objects, and hitting compile to spit out a native Windows .exe was magic.
Era 2: The Mid 2000s — Raw Sockets, Perl & The World of Warcraft Boom
As internet connections speeded up, my focus shifted into network protocols and web automation.
- mIRC Scripting (MSL) & Raw Sockets: Long before Discord bots existed, I spent years building network defence bots like SecureServ. We opened raw TCP sockets (
sockopen/sockwrite), parsed real-time IRC server notices, queried DNSBL blocklists, and dropped automated network bans. - Perl for Web Scraping: During the mid-2000s World of Warcraft boom, I ran guild websites and needed live character data. I wrote Perl CGI scripts to scrape the early Blizzard Armory, parse raw HTML tables into flat-file databases, and dynamically render raid rosters.
- PHP & Cron Jobs: For web server administration, PHP bolted onto Linux cron jobs became my standard way to rotate logs, back up databases, and monitor uptime.
Era 3: The C Trials — “Difficult, Argh!”
Eventually, I wanted raw execution speed and true, compiled Linux background daemons. So, naturally, I decided to tackle C.
Writing C was an eye-opener, but it was painful at times:
// The classic pointer dance
char *buffer = (char *)malloc(sizeof(char) * BUFFER_SIZE);
if (buffer == NULL) {
perror("Allocation failed");
exit(EXIT_FAILURE);
}
// ... three hours later: Segmentation fault (core dumped)
Wrestling with manual malloc() and free(), tracking down insidious memory leaks, debugging pointer arithmetic, and wrangling makefiles was brutal. I have huge respect for C, but as an operator trying to ship tools quickly, spending half a day chasing a segfault was the opposite of productive.
Era 4: Python — Brilliant Speed, Dependency Overhead
When I moved over to Python, it felt like a massive breath of fresh air. Development was lightning fast, syntax was readable, and the library ecosystem had a tool for everything:
- Prototyping algorithmic trading bots with
ccxtandmatplotlibin my crypto trading bot project. - Ingesting camera RTSP feeds and applying OpenCV motion filtering in CCTV-Watch.
The Catch: Dependency Sprawl
While Python is unbeatable for quick prototypes, running it across multiple production servers over years brings its own friction:
- Virtualenv Sprawl: Messing about with
venv,pip, and brokenrequirements.txtfiles on every machine. - System Python Conflicts: Upgrading Debian or Ubuntu and finding your automation broken because system Python packages shifted.
- Runtime Overhead: Packaging a simple Python script often meant dragging along heavy virtualenvs and runtime dependencies, compared to the clean simplicity of a single static binary.
Era 5: Go (Golang) — The Operator’s Sweet Spot
Around 2023, I started moving my core utilities and backend daemons over to Go (Golang). It immediately solved every headache I’d wrestled with over the previous two decades:
┌─────────────────────────────────────────────────────────────────────────────────────────────┐
│ Why Go Is the Ultimate Operator Tool │
├───────────────────────────────┬───────────────────────────────┬─────────────────────────────┤
│ Single Static Binary │ Trivial Cross-Compilation │ Effortless Concurrency │
│ • go build -> One .exe / bin │ • GOOS=linux GOARCH=amd64 │ • Native Goroutines │
│ • Zero external dependencies │ • Build for Linux on Windows │ • Buffered channels │
│ • Drop onto server & run │ • No toolchains / CMake mess │ • Lightweight worker pools │
└───────────────────────────────┴───────────────────────────────┴─────────────────────────────┘
A prime example is dImageGen, where I built a high-throughput CLI tool and embedded REST server to generate and cache AI images straight to disk.
With Go:
- Zero Runtime Dependencies & SRE Determinism: Run
go buildand you get a single static binary. Drop it onto any headless Linux box or Proxmox LXC container via SCP and it just runs — no Python virtualenv sprawl, no missing.soshared libraries, and zero version drift across servers. - Proper Concurrency Without the Pain: Goroutines and channels make parallel worker pools simple, memory-safe, and fast, avoiding Python’s GIL bottlenecks and C’s thread-locking nightmares.
- Instant Startup & Microscopic Footprint: Binaries start in microseconds, idle on single-digit megabytes of RAM, and allow you to build scratch Docker images that weigh less than 20MB.
Summary: Full Circle
Late 90s (Batch-to-EXE) ➔ Mid 00s (VB6 / Perl / MSL) ➔ Late 00s (C Daemons) ➔ 2018 (Python) ➔ Today (Go)
In a funny way, things have come full circle. The teenager in the late 90s hunting for tools to turn .bat files into standalone .exe files was after the exact same thing I value today: simple, deterministic, self-contained software that just works.
Today, paired with modern autonomous multi-agent AI workflows to write and audit code, Go has become my go-to language for building solid tools.
If you’re interested in some of the projects built across these eras, check out my retrospective on automating IRC network security in the 2000s, my build log on dImageGen: a high-concurrency Go microservice, or my reflection on getting rich with trading bots: bull runs, bear traps, and algorithmic reality.