Software engineering portfolio

Chidozie Nnachor

Senior Software Engineer

I build and modernise Java and Angular insurance software at Keylane. I lead ongoing SOAP-to-REST migration, focusing on compatibility, authorisation and automated testing.

Outside work, I explore practical problems through personal software projects, with a focus on useful tools, reliable systems and clear interfaces.

Work & projects

My engineering work at Keylane and three personal projects. Open a case study for the full story.

Personal Product Watch

I’m building a criteria-driven product watcher that compares unit prices and explains whether offers match. Try it with fictional data in the public demo.

  • TypeScript
  • Cloudflare Workers
  • D1
  • SQLite
  • GitHub Actions

Personal project

Public demo · Private repository
Read case study

Keylane — insurance software

Java and Angular insurance software, with ongoing SOAP-to-REST modernisation, authorisation, database migrations and automated testing.

  • Java
  • Angular
  • REST APIs
  • SOAP
  • OpenAPI
  • SQL
  • Liquibase
Read case study

Fusion Almere FC

I’m building a club platform for player registration, profiles and member administration.

  • Java 21
  • Spring Boot
  • Angular
  • PostgreSQL
  • Supabase

Personal project

Private repository
Read case study

HomeWizard Energy Intelligence

I’m building tools to collect smart-meter readings, explore energy history and compare when to use electricity.

  • Java
  • React
  • TypeScript
  • SQLite
  • Supabase

Personal project

Private repository
Read case study

Engineering practice: Story refinement, code review, technical notes and release documentation.

Shared toolkit: Git · IntelliJ IDEA · Gradle · Maven · JUnit · Playwright · CI/CD.

Explore how things work

Engineering Lab

Investigate a system, challenge an API contract or compare search strategies. Change a condition and inspect what follows.

Interactive · browser onlyOpen the LabClose the LabRequests · Contracts · Access · Search

Beyond the status code

Inspect the request, the saved effect, client compatibility and access decisions.

POST /demo/tasksSimulated trace · runs in your browser

Trace complete · 2 attempts · 1 record · 201 Created

Attempts
2
Records saved
1
Simulated time
190 ms
  1. 01ClientReply
  2. 02APIValidated
  3. 03ServicePrepared
  4. 04Store1 record

Operation inspector

One operation, despite a retry.

The first task commits before its reply is lost. The repeated request reuses the same idempotency key and returns the original task.

Selected operation data

{
  "id": "task-42",
  "title": "Review API contract"
}
Inspect event timeline Simulated milliseconds
  1. 0–10 · Client sends the task request.
  2. 10–25 · API validates the request.
  3. 25–60 · Service prepares the task.
  4. 60–90 · Store commits one record.
  5. 90–120 · Reply is lost.
  6. 120–130 · Client retries with the same key.
  7. 130–145 · API validates the retry.
  8. 145–175 · Store reuses the original result.
  9. 175–190 · Client receives the result.

The first write commits before its reply is lost. An idempotency key connects the retry to the same operation.

Simulated example; timings do not measure a real system. Keys apply to the same request body; key expiry, concurrent requests and cancellation are outside this example. No network requests or stored data.

Will this API change break a client?

Keep the client fixed and change the API. See why valid JSON alone does not guarantee compatibility.

The existing client is the application calling this API. It sends { "title": "Review API contract" } to POST /demo/tasks. It expects 201 Created, reads id and title as strings, and ignores extra response fields.

Compatible with this client · Reading the API response. Client reads task-42: Review API contract.

This client ignores fields it does not read, so adding priority leaves its existing behaviour intact.

  • PASS · Old request accepted
  • PASS · id remains a string
  • PASS · title remains a string
Original API

Required request fields: title

201 Created

{
  "id": "task-42",
  "title": "Review API contract"
}
Changed API

Required request fields: title

201 Created

{
  "id": "task-42",
  "title": "Review API contract",
  "priority": "normal"
}

Safer rollout: Keep the added field optional for existing clients; check stricter clients separately.

What makes the other changes break?
  • Rename title to name: the client no longer finds the title it reads.
  • Change id to a number: the client expects a string, so decoding fails.
  • Require priority in the request: the old request omits it, so validation returns 400 before the client can read a task.

These results apply to the client defined above. A stricter client could reject extra fields; other clients may tolerate different changes. Review actual consumers before changing a real API.

Simulated example · runs in your browser · no network requests or saved changes. Read about my API work

DECISION /demo/articles/draft-42Fictional publishing workspace

Signed in does not mean allowed.

Can this person act on this record? Change the selections to see which actions are allowed.

BLOCK · 403 Forbidden. Reviewer and editor roles cannot publish in this example.

  1. PASS · IdentityThe user is signed in.
  2. PASS · WorkspaceThe record belongs to the assigned workspace.
  3. STOP · PermissionReviewer and editor roles cannot publish in this example.
  4. NOT RUN · Record stateAn earlier check stopped the operation.

Action blocked. The record is neither read nor changed.

Read the fictional policy

Signed-in reviewers, editors and administrators may read records in their assigned workspace. Only administrators may publish drafts there. No role can access another workspace or publish archived records. Missing or unknown context permits no operation.

Fictional permissions demo with no real accounts, network requests or saved changes. Real services must check permissions on the server for every request. OWASP guidance (opens in a new tab).

Find a route

Same grid, different search strategy. Compare breadth-first search (BFS) with depth-first search (DFS).

.......
.#####.
.#####.
S..#..G
.#...#.
.#####.
.......

S StartG Goal# Wall· Visited○ Pending@ Current+ Route

BFS explores in layers; DFS follows a branch before backtracking.

BFS uses a queue. With equally weighted moves, its first route to the goal is a shortest route. DFS uses a stack and can find a longer route.

Moves have equal cost: up, right, down or left. Walls cannot be crossed. The same selections produce the same search. The example runs entirely in your browser.

Read the search trace and comparison

BFS takes the oldest pending cell; DFS takes the newest. Neighbours are considered up, right, down, left. The choice changes both the route and how much of the board is explored. Neither algorithm is always faster on every board.

Same board · completed searches
SearchMovesExplored
BFS824
DFS1213
In the two-route example, the shortest route takes 8 moves through the lower passage. Following the upper branch takes 12 moves. A blocked goal has no route.

Professional experience

Software engineering in the Netherlands and Scotland, following earlier roles in banking.

Sep 2019 — PresentNetherlands

Senior Software Engineer

Keylane

I deliver insurance features across Java, Angular and relational databases, from solution analysis to release.

Responsibilities at Keylane
  • Lead ongoing SOAP-to-REST modernisation, including API design, authorisation and test strategy.
  • Deliver Angular workflows, policy business rules and Liquibase database migrations.
  • Modernise regression tests, investigate defects and add unit, integration and Playwright coverage.
  • Own solution analysis, review changes and support demos, sign-off and release documentation.
  • Contribute to AI-assisted developer tooling with testing and human review.
May — Aug 2018Aberdeen, UK

Software Developer

Scotland’s Rural College

I helped design and implement a portal for field-trials data.

Responsibilities at Scotland’s Rural College
  • Worked on field-data collection and presentation.
  • Contributed to user authentication and authorisation.
2014 — 2016Nigeria

Cash Operations & Customer Front Desk Lead

First Bank

I led cash operations and customer service, including vault and ATM processes.

Responsibilities at First Bank
  • Managed vault and ATM operations and investigated operational problems.
  • Handled customer enquiries and coordinated with other departments.

From banking to software

I studied economics and worked in banking operations before completing an MSc in Information Technology at the University of Aberdeen.

My banking roles covered customer service, cash handling, and ATM operations. In software work, I still start by asking how a process works in practice before translating it into requirements.

Education

MSc, Information Technology University of Aberdeen, Scotland

2018 — 2019

BSc, Economics University of Nigeria, Nsukka

2006 — 2010

Contact me

Send me an email about engineering roles or any of the projects here.