Gerald Ikem

Backend engineer. Payments now, machine learning next.

I build the Java and Spring Boot services behind checkout, foreign-exchange rates and merchant onboarding at Payaza. I’m also studying for a Master’s in Computer Science at the University of Illinois, and pointing my side projects at machine learning.

Woodbridge, Ontario, near Toronto. Open to backend roles, hybrid in the GTA or remote.

Your request for this page

Measuring. Your browser records how long each step of loading this page took, and the trace appears here once it has finished.

Measured by your browser just now. Point at a row, or tab to it, to see what the step was.

Work

Three roles and two degrees since 2019, often more than one at a time. Pick a row to jump to the details.

Career, as a traceWorkStudyPlanned

Backend engineer, Payaza

Nov 2025 to now

  • Built a foreign-exchange rate module end to end in Java 17 and Spring Boot: buy and sell rates per currency pair, a change history you can filter by currency, and analytics endpoints that tie every rate to its source.
  • Extended the checkout payment service with Redis-cached fee recalculation, rejection of duplicate payment references, rounding per currency and support for ZAR, AED and XAF. Replaced console output with structured, asynchronous logging.
  • Secured MFA administration in the back office: TOTP soft-token provisioning, an API to switch MFA on or off, callers checked against the admin user store, and an audit entry for every privileged change.
  • Found why MFA updates were silently reverting in a multi-tenant service: the re-read ran before a tenant was bound. Binding the tenant context first and forcing a transactional flush made the settings stick.
  • Fixed three notification-settings defects (updates that reverted, came back blank or reached old recipients) and wrote the service’s first unit tests.
  • Shipped merchant onboarding features: scheduled reminder emails, admin uploads of KYC documents on a business’s behalf, and country, currency and bank lookup APIs.

Try paying twice

The same payment can reach a server twice: a client retries after a timeout, or someone taps Pay again. The checkout service refuses a reference it has already seen, so the customer is charged once. This is a small model of that check. It runs in your browser and no money moves.

Payment referencePZ-7KQ2MX

    No requests yet. Press Pay, then press it again.

    Web developer, part-time, Believer’s LoveWorld

    Sep 2021 to now

    • Maintain the ReachOut World Day and ROCK Solid campaign websites, improving form validation, accessibility, and the sign-up and donation flows.
    • Adapted Linkify into the organization’s campaign-link tool, with branded short URLs, social previews and click tracking.

    IT intern, Credit Direct

    Nov 2019 to Aug 2020, Lagos

    Education

    University of Illinois Urbana-Champaign

    Master of Computer Science, part-time. Aug 2026 to May 2028 (expected).

    Coursework includes Applied Machine Learning (CS 441).

    York University

    Honours BSc, Computer Science. Sep 2020 to Apr 2025.

    What I work with

    Languages
    Java 17 and 21, Kotlin, Python, TypeScript, SQL, C and C++
    Backend
    Spring Boot, Spring Security, Spring Data JPA and Hibernate, JDBC, REST, JWT, Flyway, Node.js
    Data
    PostgreSQL, Redis, SQLite, HikariCP
    Cloud and delivery
    AWS (EC2, VPC, Lambda, API Gateway, S3, IAM, EKS), Docker, Kubernetes, GitHub Actions, Cloudflare Workers
    Testing
    JUnit 5, Testcontainers, integration tests against real databases
    Machine learning
    PyTorch, scikit-learn, pandas, Hugging Face, Whisper, ranking and calibration metrics

    Projects

    What I build on my own time. The first three get the long version.

    HummleIn progress

    A private read-aloud app that runs on your own computer: drafts, articles and web novels read by expressive voices, with nothing sent to a cloud. Before building the app, I am proving the voice engine can carry it.

    • Benchmarked five open-source text-to-speech models on an AMD RX 7900 XTX, comparing q8_0 GGUF on Vulkan with PyTorch on ROCm.
    • Built automatic quality gates instead of trusting my ears: Whisper checks every word across 60 takes per engine, and CAM++ speaker similarity checks the voice stays the same person.
    • Traced a drop in voice identity during emotional lines to a linear resample of a 48 kHz reference. A proper 16 kHz resample raised the worst speaker similarity from 0.57 to 0.86.
    • Caught narrators drifting into a British accent with an accent-ID model and a rhoticity measure in Praat, and traced it to the voice-design prompt. Dropped an emotion classifier as a gate after it agreed with blind human ratings only 24% of the time.
    • Python
    • PyTorch on ROCm
    • llama.cpp (GGUF)
    • Whisper
    • CAM++
    Generation speed across five models on one GPUReal-time factor: seconds of compute per second of speech. Lower is faster.
    GGUF q8_0 on Vulkan0.21–0.35
    PyTorch on ROCm0.75–1.00

    Linkify

    Short links with custom slugs, expiry, QR codes and click analytics, built so that measuring a click never slows the redirect down. It also powers the campaign links at Believer’s LoveWorld.

    • Clicks are recorded on a bounded background executor. When it is full, work is shed and counted rather than pushed back onto the redirect.
    • Unique visitors are counted with a SHA-256 hash that includes the date, so no IP address is stored and nobody can be followed from one day to the next.
    • 244 tests, with integration tests on real PostgreSQL and Redis through Testcontainers. They prove that simultaneous claims on one custom slug produce exactly one winner, and that replaying a used refresh token revokes the whole session family.
    • Java 21
    • Spring Boot
    • PostgreSQL
    • Redis
    • Next.js
    • TypeScript
    How Linkify resolves a short link

    GET /launch

    1. Redis GEThit
    2. Check expirystill live
    3. Respond302 to the destination
    4. Record the clickon a background worker

    Most clicks look like this: one Redis read and an expiry check. The click is handed to a bounded background worker, so the visitor never waits for analytics.

    GET /zz9x

    1. Redis GETmiss
    2. PostgreSQL lookupnot found
    3. Cache the missfor 60 seconds
    4. Respondnot-found page

    Bots scan for codes that don’t exist. Caching the miss for a minute turns a burst of probes into one database query instead of thousands.

    GET /spring-sale

    1. Redis GEThit
    2. Check expiryexpired
    3. Responda page that explains the link expired

    The cached entry carries the link’s expiry, and it is checked on every hit. A stale cache can never keep an expired link alive.

    GET /launch

    1. Redis GETerror, counted
    2. PostgreSQL lookupfound
    3. Respond302 to the destination

    A cache failure is not a site failure. The resolver falls back to PostgreSQL. The instance reports itself not ready, so the load balancer drains it, but stays live, so it isn’t restarted into a storm.

    Bars show the order of the work, not measured timings.

    QuickRead

    A study app that turns documents, web pages and recordings into summaries, questions with sources and study cards. Answers quote the original text exactly, so you can check them.

    • One Python engine serves both a command-line tool and a Pyodide web worker, so text extraction, OCR for scanned PDFs and speech transcription run in the browser.
    • Handles files up to 1 GB and recordings up to 4 hours.
    • Compared passage retrieval against TF-IDF baselines on 60 labelled questions, using precision, recall and reciprocal rank.
    • Python
    • Pyodide
    • React
    • TypeScript
    • Cloudflare Workers, D1 and R2
    • Supabase Auth

    Also built

    • Threadfern

      A concurrent web crawler with a searchable index of what it finds.

      Bounded worker pool, robots.txt rules, request pacing, and page and link writes that commit together or not at all.

      Java 17, JDBC, PostgreSQL, Docker

    • Matchday ML

      Pregame win, draw and loss forecasts for the Premier League, La Liga, the Champions League, the NBA and the WNBA.

      53.4% accuracy on a 1,140-match historical football test, with models compared on log loss, Brier score and calibration, not accuracy alone. Forecasts are timestamped and stored, so live predictions stay separate from backtests.

      Python, scikit-learn, SQLite, Docker, Next.js

    • ReelRank

      Film recommendations from the films you already love.

      EASE collaborative filtering beat a popularity baseline by 56.7% on NDCG@10 (0.1118 against 0.0713) over MovieLens 32M. The trained model runs in the browser and ranks identically to Python on 12 reference cases.

      Python, pandas, SciPy, JavaScript

    • Skyloom

      A weather app whose sky changes with the hourly forecast.

      A Three.js sky driven by Open-Meteo data, with rain and wind charts, radar, moon phases and a reduced-motion mode.

      React, TypeScript, React Three Fiber, Cloudflare Workers

    • This Is It 2.0 avatars

      An avatar maker for This Is It 2.0, an event in Winnipeg in August 2026.

      Add a photo, frame it with pinch and drag, and export a share-ready image, all on the phone.

      React, TypeScript, Canvas, Netlify

    What’s next

    Payments taught me what reliable software takes: a request that may arrive twice, money in currencies with different rules, and an audit trail nobody gets to skip.

    I want to bring that discipline to machine learning systems, where much of the hard work is data plumbing, evaluation and serving rather than the model itself. That’s why I’m doing the Master’s at Illinois, starting with Applied Machine Learning, and why Hummle is mostly measurement so far: speed, word accuracy and voice identity, checked by code rather than guessed by ear.

    Right now I’m looking for a backend or platform role on a team that runs serious systems, at a bank, a payments company or a large enterprise, ideally one where I can grow toward ML infrastructure.

    Off the clock

    I collect comics, mostly DC and Marvel omnibuses, and read each run in order. There are 56 books on my shelf (31 of them omnibuses), 2 on order and 25 on the wishlist.

    I also build LEGO: six sets so far, from the James Bond Aston Martin to the 1966 Batmobile, with the Black Pearl and Arkham Asylum still in their boxes. And I play basketball, swim and collect books.

    Browse the shelf and read my notes on each book

    Contact

    The quickest way to reach me is email.

    Based in Woodbridge, Ontario, near Toronto. Authorized to work in Canada and the United States.