Java · SQL · Full-stack development

Kheagen Haskins

Kheagen Haskins holding a bulldog puppy

Full-stack developer working in Java and SQL, with most of my work on the backend. I am the only developer at a managed IT services provider, where I designed and built the reporting engine that produces every client's monthly report. Teaching is how I got here. A psychology degree led me into it, and teaching Java led me into building software full time.

Languages
Primary
Java, SQL Server
Working knowledge
HTML, CSS, JavaScript, Python, Rust

Experience

  1. Managed IT services provider

    Full-stack developer · to present

    I designed and built the company's reporting engine. It runs in production and covers every device the company manages, from laptops and servers to printers and switches.

    Design decisions
    24
    Each one is recorded in an architecture decision record, and each one is mine.
    Lines of code
    94,000
    • Java 73,000
    • SQL 14,000
    • Other 7,000
    The count leaves out blank lines and comments. I wrote about 90% of it, and AI wrote the rest.
    Time for 100 reports
    20 min
    • Engine 20 min
    • Old tool over 1 h
    Measured before any work on the engine's speed.

    One half of the engine syncs data from ten vendor systems into one database. The other half reads that data back out and turns it into configurable reports.

    1. 10 data sources Ticketing, monitoring, security, backups, training

      I built the API layers that read the company's ticketing, monitoring, security, backup and training systems over REST, GraphQL and JSON-RPC, and its data warehouse over JDBC.

    2. 1 database SQL Server, synced on a schedule

      I designed the schema and administer the SQL Server database.

    3. Domain model Devices, tickets, agents

      I designed the business objects, which stay stable when the database changes.

    4. Client reports PDF and Excel, one per client, monthly

      I design the PDF and Excel reports, laying the PDFs out in HTML and CSS. I also built the web page that configures each report.

    Why the company built its own engine

    The company used to build its reports with a vendor's reporting tool. The vendor then released a new analytics product, which offered new data but very little of what the old reports used. The old tool stayed the only way to reach the data the old reports used, even though the vendor had stopped maintaining it. It was full of bugs, and it depended on an API the vendor had deprecated. Our own engine copies that data into a database the company controls, so it can shape its reports however it wants.

    How I review my code

    As the company's only developer, I have always been the one Java engineer on the job. In place of peer review, I run layered AI audits, each covering one concern: correctness, conventions, documentation or test coverage. I repeat them until the findings turn trivial. They catch real mistakes, but a senior engineer sees what they miss, which is why working with experienced developers is a large part of what I want next.

    Service desk administration

    Alongside the engine, I am the system administrator for the company's service desk system. I configure its ticket types and workflows, and take on the occasional ticket that needs a developer. One was a one-off request to migrate a client's WordPress site. While upgrading it to a current version of PHP, I found unfamiliar files and altered settings across the site. It had gone unpatched for a long time and had been compromised, so I cleaned it out before the migration went ahead.

Other roles

  1. TurtleJar

    Java tutor · to present
    Java and Python tutoring for high school and first-year university students.

    Alongside my development work I tutor Java, both to Grade 10 to 12 students on the IEB syllabus and to university students taking it in their first years. I also teach Python to first years. Most of the work is diagnosis. I find the idea a student has actually misunderstood, then explain it in terms they already understand.

  2. Independent school, Johannesburg

    Coding, robotics and IT teacher · to
    Taught IEB Information Technology in Java, and wrote the textbook for the course.

    From 2021 I taught IEB Information Technology to Grades 10 to 12, a syllabus taught in Java. I wrote a textbook for the course and coached matric students through their final-year projects, which meant explaining design, debugging and program structure to people meeting them for the first time.

    I joined as a coding and robotics teacher for primary school children, using LEGO Mindstorms EV3 robots and Swift Playgrounds. When Covid moved lessons online, I taught myself web development and taught HTML and CSS to Grade 4s.

  3. Royal Sitting Services

    Co-founder · to
    Co-founded a pet-sitting business that grew past what two people could run.

    My partner and I started a pet-sitting business while I was at college. Bookings filled up faster than the two of us could take them, so we interviewed and hired more sitters to keep up. Covid ended the business in 2020, just as I began teaching.

  4. Retail promotions agency

    Junior sales representative · to
    Sold GPS devices in Makro, approaching every shopper cold.

    I sold TomTom GPS devices to shoppers in Makro, a large retail chain, approaching each person cold. The job built my confidence in talking to strangers and persuading them.

Hard problems

These are the hardest problems I have solved in the reporting engine. I worked out how each of them should work myself. My starting point was the old reports, and sometimes the API behind their data.

  1. Syncing from a data warehouse that charges per query

    The hardest source to sync was a Snowflake data warehouse, reached through a JDBC driver that sends each query over HTTPS. Loading its tables into an empty database was quick to build. Keeping them up to date afterwards was the real work, and each fix exposed the next problem.

    Average update sync
    180 s
    Across all ten sources. The first working version took several hours. A routine update moves less data than a first load, but runs far more logic.
    1. Testing without live calls Every query spent paid credits

      Every query spent paid credits, so I could not test against the real source. I cached one real pull as test data, then built a fake server that serves it and misbehaves on demand, by going silent or changing its schema.

    2. Schema changes The vendor changed it without notice

      The vendor changed its schema without notice, so I built schema change detection into the sync.

    3. Slow or hung A slow response looked like a dead one

      Syncs began to hang, and nothing could tell a slow response from a dead one. I moved to paging, and found the page size the source could serve reliably. Paging then raised the questions every sync has to answer, such as what to roll back when the sixth page fails, and what to do with half a page.

    4. Measuring Some tables took ten times longer

      I built diagnostic tables into the database that record each sync's errors and the time taken for every source and table. A day or two of production data showed some tables taking ten times longer than others, so those tables now sync on their own schedule.

    5. Finding changed rows Whole-table compares failed at 4 million rows

      Comparing whole tables fell over at four million rows, where one table took an hour to sync. A MERGE statement was faster but still slow. The sync now pulls changes in pages, sorted on a key chosen per table: a change-tracking column where the table has one, and a column I worked out myself where it does not.

    6. History A late request for every record's past

      A late request asked for the history of every record, so I added slowly changing dimension (SCD) tracking to every source. It keeps each past version of a record alongside the current one. Each table has its own tracking policy for now, and I am working towards a general set of rules that new tables can follow.

    • Snowflake
    • JDBC
    • Paging
    • Incremental sync
    • Slowly changing dimensions
  2. Separating the domain model from the schema

    My first classes copied their tables, so a changed table meant a redesigned class. Every piece of code that used the class then changed with it. I remodelled the domain on what the business means by a device, a ticket or an agent, and wrote a translation layer that maps database rows to those objects. A change to the database, or to a domain object, is now made in that layer alone.

    • Domain modelling
    • Anti-corruption layer
  3. Branded charts in PDF reports

    The reports needed charts in the company's branding. I hand-wrote each chart as an SVG template that the engine fills with a client's data. Marketing can therefore design a chart of their own in SVG and hand it to me to add to a report.

    • SVG
    • Templating

Skills

  • Java

    • Java 25
    • Framework-free
    • JPMS modules
    • Records and sealed types
    • Virtual threads
    • JUnit 5
    • Mockito

    Hover to read how I use itTap to read how I use it

    Java

    The engine is a set of libraries that its apps call, rather than a framework that calls them. It is built on the standard Java APIs and a few small, focused libraries, and I wire it together by hand with plain constructor calls. A stack trace therefore follows my own code from the call to the failure.

    Each class receives its dependencies through its constructor, typed as interfaces, so tests pass in their own doubles. The modules seal their internals under JPMS, the Java module system, so one module reaches another only through what that module exports.

  • Data

    • SQL Server
    • Data warehousing
    • JDBC
    • HikariCP

    Hover to read how I use itTap to read how I use it

    Data

    I wrote the code that generates the engine's SQL and protects it from SQL injection. The data sync loads only new and changed rows, and recovers when a database connection drops.

  • APIs

    • REST
    • GraphQL
    • JSON-RPC
    • OAuth 2.0

    Hover to read how I use itTap to read how I use it

    APIs

    Each vendor connection keeps to that vendor's rate limits and retries failed calls with growing delays. Login tokens refresh safely while many calls run at once.

  • Reports and apps

    • OpenHTMLToPDF
    • Apache POI
    • JavaFX
    • Undertow
    • jpackage

    Hover to read how I use itTap to read how I use it

    Reports and apps

    The engine produces Excel workbooks and PDF reports with charts. Its apps run on Windows as standalone programs that bundle their own Java runtime.

  • Tooling

    • Rust
    • Python
    • Maven
    • JaCoCo
    • Checkstyle
    • PMD
    • Spotless
    • Docker
    • Git

    Hover to read how I use itTap to read how I use it

    Tooling

    I write command-line tools in Rust for the jobs around a build that are slow by hand or easy to get wrong. One of them counts a codebase's lines of code, leaving out comments and blank lines, and it produced the line count for the reporting engine above.

    Every Maven module takes its dependency versions from one shared bill of materials (BOM). A module's build fails when its test coverage drops below a set minimum, and Checkstyle, PMD and Spotless check the code's style. SQL Server runs in Docker for development and testing.

Projects

Recent

These show how I build software now, with development experience behind me.

  • GUI Exams

    2026 · GitHub

    Java mock exams for IEB Information Technology, where the learner's printed answers drive an animation.

    • Java
    • Swing
    • Records
    • Teaching
    Read more

    GUI Exams are Java mock exams for the IEB Information Technology syllabus, for Grades 10 to 12. In a standard paper, the learner's program prints its answers as text. Here a window reads that text line by line and animates it. In the Farm Drones paper, each line the program prints sends a drone across a farm to water a field, and a wrong battery calculation shows up as a drone falling out of the sky.

    The window marks each part green, amber or red, and explains anything that is wrong.

  • Slicket

    2026 · GitHub

    A ticketing system in Rust, built on an entity component system, with every AI contribution in its own commit.

    • Rust
    • Entity component system
    • Cargo workspace
    Read more

    Slicket is a ticketing system I am building in Rust. I administer a well-known service desk system at work and find it complicated to use, so Slicket is my attempt at one that feels better. Its backend is an entity component system (ECS), a design where each thing, such as a ticket, is a bare ID with its data stored in separate components. Systems then run the logic over every ID that has the components they need. It is at an early stage of design.

    It also shows how I work with AI. On its dev branch, my work and the AI's go in separate commits, and each commit's author records whose work it contains. Anyone can see exactly where I used AI.

Earlier

I built these before I had any development experience, while I was teaching and then studying Java full time.

  • WordCheat

    2025 · GitHub

    Lists every playable Words With Friends move, highest score first.

    • JavaFX
    • Move search
    • JUnit 5
    Read more

    WordCheat is a desktop helper for the Words With Friends word game. The player drags the board and their letters into it, and it lists every move they can play, highest score first. It checks each placement against a list of about 168,000 English words. The check covers every crossing word the move forms as well, and each valid move is scored with the game's letter values and bonus squares.

    I built it because my mother always beats me at the game.

  • HackMaster

    2024 · GitHub

    The terminal hacking puzzle from Fallout 3 and 4, rebuilt as a desktop game.

    • JavaFX
    • MVC
    • Observer pattern
    Read more

    HackMaster recreates the terminal hacking puzzle from the Fallout 3 and 4 video games. The player picks a password from a screen of words, and each wrong guess reports how many letters are in the right place.

    Its screens update themselves whenever the game state changes, and it comes with a Windows installer.

Education

  1. 2020 to present

    Self-taught programming

    Certificates

    I learnt to program through my teaching, my development work and my own projects. I also relearnt maths on Brilliant so that I could use it as a tool. Each project led into the next.

    1. Noise generator Draws natural-looking textures and terrain from maths
    2. Maths The maths behind the noise
    3. Physics engine A small one, written myself
    4. ECS architecture The way data is laid out drives the design
  2. to

    Professional Java

    Full-time independent study

    After leaving teaching, I spent most of a year learning Java as industry uses it rather than as a school syllabus teaches it. I learnt Git, and worked through Codecademy's courses on Java and on the Spring framework.

  3. to

    Bachelor of Arts

    I completed a three-year BA at Varsity College Sandton (now Emeris), majoring in Psychology and Communication Science.

  4. 2014

    Matric

    I earned my National Senior Certificate at Maragon Private Schools (now Crawford Ruimsig).

Extras

Coding philosophy

How I choose tools, why my systems keep frameworks at arm's length, and how I work with AI.

Hobbies

Outside work I write code for myself, play chess, study mathematics and read computer science.