Systems that
hold up.

Most of my work keeps a business running. Some of it starts with “wouldn't it be funny if…?” I take both seriously.

01 / SELECTED WORK

Three problems
worth solving.

Short case studies from the day job, kept generic on purpose: no internal systems, just the problem, the decision and what it cost.

2024 — 2026 · TELECOM ACQUISITIONS

Making supplier onboarding
repeatable.

AZURE · SERVICE BUS · EVENT-DRIVEN · DOMAIN MODELLING · MENTORING
Problem
Every supplier had its own API, data formats, rules and failure modes. Each new one meant custom work spread across sales journeys and back-office systems.
Decision
A supplier-agnostic integration layer: one internal domain model, an adapter per supplier, and business events on a message bus instead of point-to-point calls. I designed it and owned it from domain modelling through deployment, monitoring and production support.
Trade-off
More design up front, and eventual consistency to handle between services, in exchange for a core that doesn't change every time a supplier does.
Result
Adding a supplier became repeatable work instead of a project, coupling between systems dropped, and high-volume sales stayed reliable and observable. I also mentored two developers on the team.
2023 — 2024 · RAYMOND JAMES

Upgrading a regulated platform
without the drama.

PHP 8 · MYSQL 8 · PHPUNIT · REGRESSION TESTING · INCREMENTAL MIGRATION
Problem
Business-critical wealth-management systems needed to move from PHP 7.4 to 8.2 and from MySQL 5 to 8. The code quietly relied on behaviour the new versions no longer tolerate: stricter SQL grouping, invalid dates, warnings that become errors.
Decision
Build a regression-test baseline first, then fix compatibility issues incrementally across applications and databases, instead of rewriting.
Trade-off
Time spent on tests before any visible progress, in exchange for releases everyone could trust.
Result
Migration and release risk went down without sacrificing stability for the people who depended on the platform.
2019 — 2021 · DEKO

Replacing a monolith without
stopping the business.

JAVA · DDD · EVENT STORMING · STRANGLER PATTERN · AWS SQS
Problem
A long-running lending platform had grown into a legacy monolith, and the lending operations it supported couldn't stop while it was replaced.
Decision
Domain-driven design and event storming to find the real business boundaries, then the Strangler Pattern: move one capability at a time into Java services, with Go and Python components, connected by asynchronous messaging on AWS SQS.
Trade-off
A slower, staged migration with old and new running side by side, instead of a big-bang rewrite and a risky cut-over.
Result
Business-critical lending kept running throughout, while capabilities moved to the new platform step by step.
02 / BEHIND THE SCENES

Make the pieces
work together.

The best integration is one the person using it never has to think about.

A SIMPLIFIED PICTURE OF THE KIND OF PLATFORM I DESIGN AND RUN
Customer web apps, internal tools and a self-service portal call a core API and an integration API, which share a database. The integration API calls partner APIs directly. The APIs publish events to a message bus; independent workers subscribe and sync each event to an external SaaS, comms or messaging platform. Status feeds and callbacks, some arriving by webhook, are published back to the bus.CLIENTSCLOUD PLATFORMEXTERNALCustomerweb appsInternaltoolsSelf-serviceportalCoreAPIDatabaseIntegrationAPIMESSAGE BUSSync workerComms workerNotify workerSaaS platformComms platformMessaging providerPartner APIsstatus feedstatus callbacksHTTP / RESTevents & feedswebhooksCustomer web apps, internal tools and a self-service portal call a core API and an integration API, which share a database. The integration API calls partner APIs directly. The APIs publish events to a message bus; independent workers subscribe and sync each event to an external SaaS, comms or messaging platform. Status feeds and callbacks, some arriving by webhook, are published back to the bus.CLIENTSCLOUD PLATFORMEXTERNALCustomerweb appsInternaltoolsSelf-serviceportalCoreAPIDatabaseIntegrationAPIMESSAGE BUSSync workerComms workerNotify workerSaaSplatformCommsplatformMessagingproviderPartnerAPIsHTTP / RESTevents & feedswebhooks
  • Azure & AWS
  • Containers
  • Serverless functions
  • Message queues
  • Infrastructure as code
  • CI/CD
  • Monitoring & tracing
TRY THE ORDER-FLOW SIMULATION ↗
03 / AFTER HOURS

Serious about
playing.

WORD DUEL / WORD GAME

One letter.
A whole new word.

A real-time word game against a friend or the computer. The server referees every move, so the rules hold even when both players act at once.

PLAY THE GAME ↗
LAST ONE STANDING / PARTY GAME

Can you feel
five seconds?

A party game for 2–8 players, each on their own phone and kept in sync in real time. Easy to explain. Much harder to master.

PLAY THE GAME ↗
04 / THE WAY I WORK

Five things
I hold to.

These are the habits I bring to any team, and the ones I try to pass on.

01

Design for failure.

Timeouts, retries, idempotency and outboxes go in on day one, not after the first incident. Partners will be slow. Queues will go down.

02

Make change safe.

A test baseline first, then small, reversible steps. I'd rather modernise around what already works than bet the business on a rewrite.

03

Model the business first.

Domain modelling and event storming before code. Getting the boundaries right saves more time than any clever implementation.

04

Own it in production.

Logging, tracing and alerts are part of the feature. If I built it, I want to know when it's unhappy, before a customer does.

05

Raise the team.

Mentoring, honest code reviews and writing decisions down, so knowledge doesn't live in one person's head.

HOW I GOT HERE ↗