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 am the company's only developer. I designed and built its reporting platform, which syncs data from nine vendor systems into one database and turns that data into each client's monthly report.

    Responsibilities

    • Full-stack engineer

      I write all of the code, from the SQL that builds the database to the web server that runs the reports.

      1. SQL schema
      2. SQL queries
      3. Java data access
      4. PDF reports
      5. Web server
    • Database administrator

      I created the SQL Server database, change it as the platform grows, and keep it healthy.

    • Tester

      I write and run every test, and I configured the CI/CD pipeline that runs them.

    • DevOps

      I deploy the platform to our on-premises production server, following a runbook I wrote.

    Achievements

    Developer
    1
    I built a full production data platform by myself, and it produces every client's monthly report.
    Report speed
    2×
    Speed
    Data per report
    • Legacy system
    • My platform
    Reports generate roughly twice as fast as on the legacy system, and include almost twice as much data.
    Deployment
    Automated
    I automated the deployment pipeline to our on-premises server. The deployment script checks the new version's health and rolls it back when the check fails.
    How I review my code

    As the company's sole developer, I review all of my own code. My experience of peer review comes from teaching, where senior teachers moderated my exam papers and I moderated theirs. At work, 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.

Other roles

  1. TurtleJar

    Java tutor · to present
    Java, SQL and Python tutoring for high school and university students.

    Alongside my development work I tutor students from Grade 10 on the IEB syllabus up to their first years at university. Most of the work is diagnosis. I find the idea a student has actually misunderstood, then explain it in terms they already understand.

    Responsibilities

    • Tutor

      I explain and teach Java, SQL and Python to students at every level.

    Achievements

    Student work
    Exhibited
    Students I tutor have had their code featured in local school exhibitions.
  2. Independent school, Johannesburg

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

    I joined in 2020 to teach coding and robotics to primary school children, using LEGO Mindstorms EV3 robots and Swift Playgrounds. From 2021 I also 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.

    Responsibilities

    • Curriculum designer

      When Covid moved lessons online, I wrote the school's coding and robotics syllabus from scratch, and the school kept it after Covid ended. Other schools later added coding and robotics, but this syllabus was ours alone. By Grade 9, students had published their own CV website.

      1. Grade 3: binary
      2. Grade 4: HTML
      3. Grade 9: a live CV in HTML, CSS and JavaScript
    • Examiner

      I set every test and exam I gave. Senior IT teachers moderated each paper, round after round, until they found nothing left to fix.

    • Moderator

      I moderated many other IT teachers' exams, as well as the school's own Computer Applications Technology (CAT) exams.

    • Remedial educator

      I taught coding successfully to students with a range of disabilities, including cerebral palsy and autism.

    Achievements

    IT average
    +20%
    I raised the average percentage for IT by over 20%.
    Youngest coders
    Grade 3
    My syllabus taught binary to Grade 3s and HTML to Grade 4s, and both age groups did well.
  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.

    Responsibilities

    • Sales

      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 billed per query

    The hardest source to sync was a data warehouse billed per query. 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.

    1. Schema changes The vendor changed it without notice

      The vendor changed its schema without notice. Before the sync fetches anything, it now checks that it can map every column it will write, and it reports a mismatch as a schema failure.

    2. 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 reading 50,000 rows a page, with a time limit on each page, and a stalled page is retried on a fresh connection. 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.

    3. Measuring A few tables took far 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 a few tables taking far longer than the rest. I therefore moved those tables onto a schedule of their own, reading them four times a month to save warehouse credit.

    4. Finding changed rows Reading whole tables cost too much

      Reading every table whole on every run cost too much on the largest ones. Where a table has change-tracking columns, the sync now pulls only the rows that changed since its last run, in pages sorted on the table's key. A table without them is read whole, and the largest of those are read at most once a day.

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

      To meet a late request for the history of every record, I added slowly changing dimension (SCD) tracking to the warehouse's three main tables and to seven tables from a second source. It keeps each past version of a record alongside the current one. When I measured the warehouse's history, 588,000 stored versions held only 50,000 distinct states, so a new version is kept only when a record actually changes. Each table has its own tracking policy for now, and I am working towards a general set of rules that new tables can follow.

    • Data warehousing
    • Paging
    • Incremental sync
    • Slowly changing dimensions
  2. Replacing hundreds of API calls with one query

    A vendor's REST API returned records one client and one page at a time, meaning collecting all of them took hundreds of requests in a row. I found a way to fetch the same data with a single query, and moved the collection onto it. Adding a new kind of data no longer means new API code. It takes a query file, a mapping from its columns to a Java record, and the table the rows land in.

    Collection speed
    186×
    The single query against the paged REST calls, as measured and recorded in the decision record that made the switch.
    • SQL
    • REST
    • Performance
  3. Separating the reports from the schema

    My first classes copied their tables. As a result, a changed table meant a redesigned class. Every piece of code that used the class then changed with it. I split the data layer into thirteen areas. Eleven match a part of the report, such as tickets, hardware, backups, patches, email security and security training. The other two hold the client list and each report's saved settings. Each area is an interface that returns typed records, and its SQL and implementation stay hidden behind it. A change to the database is now made behind those interfaces, where the reports never see it.

    • Domain modelling
    • Data access layer
  4. Branded charts in PDF reports

    The reports needed charts in the company's branding. The engine draws each chart as SVG from a client's data, with no chart library: eight chart types, from bar and line charts to gauges, each written in Java. The cover page, stat cards and score boxes are SVG files with slots the engine fills, so marketing can change their layout by editing a file. A report that still contains an unfilled slot fails rather than reaching a client.

    • 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.

    The sync's classes receive their dependencies through their constructors, meaning tests can pass in their own doubles. The sync runs its sources in the order their data depends on each other, and runs independent sources at the same time on virtual threads. The library modules seal their internals under JPMS, the Java module system. As a result, one module reaches another only through what that module exports.

  • Data

    • SQL Server
    • Data warehousing
    • HikariCP

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

    Data

    I wrote the code that generates the sync's SQL from the schema and protects it from SQL injection. Where a source reports what changed, the sync loads only new and changed rows. A stalled query is retried on a fresh connection, and a table that fails catches up on the next run.

  • APIs

    • REST
    • GraphQL
    • JSON-RPC
    • OAuth 2.0

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

    APIs

    Most vendor connections are rate-limited and retry failed calls with growing delays, waiting without holding a thread. Login tokens refresh safely while many calls run at once. Guards on the connections reject any call that could change data, since one vendor's token could reboot client machines.

  • 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. Every report keeps the same two rules: no section is ever left out, and no figure is shown for a period its data does not reach. Its apps ship as standalone programs that bundle their own Java runtime.

  • Tooling

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

    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. The reporting engine uses several of them. They build and seed its test database, update the version tags in its Javadoc, and turn its SVG icons into app icons. Another counts lines of code, leaving out comments and blank lines.

    Every Maven module takes its dependency versions from one shared bill of materials (BOM). Eight modules fail the build when their test coverage drops below a set minimum, and Checkstyle, PMD and Spotless check the code's style. Tests also enforce the architecture: SQL has to live in its own files, and the library modules cannot pull in a logging backend. SQL Server runs in Docker for development and testing, and GitHub Actions builds and deploys the apps.

Projects

  • Slicket

    2026 · GitHub

    A ticketing system in Rust, designed around 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. Slicket is my attempt at one that feels better. Its backend is designed around 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: the entity and component types are built, and the storage and systems come next.

    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.

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, to 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. 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.