Skip to main content

Engineering & architecture

How these systems are actually shaped

Six figures covering the classes of system I have worked on. Each one is drawn from the technologies and responsibilities on my CV, arranged into the conventional shape a system of that description takes.

Every figure on this page is conceptual and sanitised. None of them depicts any employer’s internal architecture. They contain no proprietary service topology, infrastructure detail, hostnames, credentials, customer data or business metrics. Where a figure names a system, that name appears on my public CV and nowhere beyond it.

Fig. 01

Property management platform, conceptual service layout

Concepts shown

  • Microservices
  • API surface
  • Object storage
  • ML inference path
  • Mobile clients

Grounded in

CV: in-house backend microservices in PHP; React Native app for iOS and Android; engagement-prediction model served via TensorFlow Serving; Docker, CI/CD and AWS S3.

Read: Property Management Platform
  1. Clients

    • Web applicationBrowser
    • Mobile applicationReact Native · iOS + Android
  2. Edge

    • API surfaceRouting · Auth · Rate limiting
  3. Services

    • ListingsPHP
    • Tenancy & operationsPHP
    • Engagement inferenceTensorFlow Serving
  4. State

    • Relational storeTransactional data
    • CacheHot reads
    • Object storageAWS S3 · media
The conventional shape of a property management platform built as in-house services: a web client and a React Native mobile client entering through one API surface, discrete services behind it, and a separately-scaled inference path for the engagement model. Object storage is drawn as its own dependency because media is the heaviest thing a property platform moves.
Fig. 02

Multi-bank funds transfer, conceptual integration surface

Concepts shown

  • Integration surface
  • Provider adapters
  • Idempotency
  • Asynchronous settlement
  • Reconciliation

Grounded in

CV: led backend development of the FIAP Transfer Service (Java, Spring Boot) across 8+ partner banks; integrated the B2B middleware with MTN Mobile Money.

Read: Multi-Bank Funds Transfer Service

Consumers

  • B2B middlewarePlatform callers
  • Internal servicesServer-to-server
Transfer serviceJava · Spring Boot

External providers

  • Partner bank adapters8+ institutions
  • Mobile moneyMTN MoMo API
  • Settlement & reconciliationAsynchronous
  • Transaction ledgerSystem of record
A funds-transfer service is a translation layer. Each partner institution exposes a different contract, a different timeout profile and a different notion of a settled transaction; the service's job is to absorb that variance so callers see one interface. The CV records this service operating across 8+ partner banks.
Fig. 03

Biller aggregation, conceptual fan-out

Concepts shown

  • Aggregation layer
  • Provider normalisation
  • Retry and failure handling
  • Reporting and audit trail

Grounded in

CV: integrated 14+ VAS billers (airtime, electricity, betting) into the B2B middleware using Laravel and Node.js; built and maintained the Biller Aggregation Platform (BAP) and BAP Reporting Service (BRS) in Node.js and Java/Spring Boot.

Read: Biller Aggregation & Value Added Services

Consumers

  • Agent applicationsRetail channel
  • B2B middlewarePartner callers
  • Support portalLaravel
Biller Aggregation PlatformNode.js · Java

External providers

  • Airtime & dataInstant settlement
  • ElectricityToken delivery
  • Betting walletsWallet top-up
  • Reporting serviceBRS · audit trail
Aggregation turns many unlike provider APIs into one stable contract. Each biller category behaves differently. Airtime settles instantly, utility tokens arrive asynchronously, and betting wallets have their own rules, so the aggregation layer owns normalisation, retries and a reporting path that can answer 'what actually happened' after the fact. The CV records 14+ VAS billers integrated.
Fig. 04

Freight management, conceptual data flow

Concepts shown

  • Telemetry ingestion
  • Third-party feeds
  • Normalisation
  • Dynamic routing

Grounded in

CV: architected a freight management system (Laravel) and companion mobile app (Kotlin); integrated third-party tracking APIs and IoT logistics data to support dynamic delivery routing.

Read: Freight Management Platform
  1. Sources

    • Driver applicationKotlin · Android
    • Third-party trackingProvider APIs
    • IoT telemetryVehicle signals
  2. Processing

    • NormalisationOne event shape
    • Position & statusCurrent state
  3. Platform

    • Freight managementLaravel
    • Dynamic routingRoute adjustment
  4. Consumers

    • Operations consoleDispatch
    • Customer visibilityDelivery status
Freight software is a shadow of a physical system, so the interesting flow is inbound: telemetry and third-party tracking arriving continuously, being normalised, and feeding routing decisions that change while a journey is already in progress. Drawn as an ingestion path rather than a request/response stack, because that is the shape of the problem.
Fig. 05

Tax compliance automation, conceptual processing path

Concepts shown

  • Document ingestion
  • NLP extraction
  • Human review gate
  • Backend of record

Grounded in

CV: built an automated tax compliance model using NLP for extracting key insights from financial data in Python; delivered backend systems for the PAYTAX ABIA and PAYTAX IBEJU government tax automation projects.

Read: Government Procurement & Tax Automation
  1. Intake

    • Financial documentsUnstructured input
  2. Extraction

    • NLP pipelinePython
    • Structured fieldsNormalised output
  3. Control

    • Human reviewApproval gate
  4. System of record

    • Compliance backendAuthoritative store
    • ReportingProgramme oversight
Government financial systems have to be correct before they are convenient, which makes the human review step structural rather than optional. The model extracts and proposes; it does not decide. Drawn as a pipeline with an explicit review gate between extraction and any downstream record.
Fig. 06

Delivery pipeline, conceptual stages

Concepts shown

  • CI/CD
  • Containerisation
  • Repeatable deploys
  • Post-deploy verification

Grounded in

CV: set up infrastructure pipelines including CI/CD, Dockerisation and AWS S3 storage for seamless deployment and system reliability.

  1. 01CommitVersion control
  2. 02Build & testAutomated checks
  3. 03Container imageDocker
  4. 04DeployPer-service release
  5. 05VerifyHealth & rollback path
The pipeline is the part of a platform that decides how often you can safely change your mind. Containerising the services and automating the path to production is what makes independent service deployment real rather than aspirational.
Interactive

What each component owns, and how it fails

Select a component. The second question is the one that matters, anyone can draw a box; the failure mode is what you only learn by operating it.

Interactive · select a component

Conceptual and sanitised. Every node answers two questions: what it owns, and how it fails.

  1. Clients

  2. Edge

  3. Services

  4. State

Engagement inference

Owns

Model serving for engagement prediction, scaled separately from the app.

Fails like this

Now in a user-facing path. Needs its own timeout and a defined degraded render when it is slow.

Decision log

The option that was rejected, and why

Architecture decision records from the systems above. Each states the alternative considered and the consequence accepted, the parts a CV bullet has no room for.

  1. One adapter per partner institutionA transfer service spanning 8+ partner banks. Each exposes a different contract, timeout profile and definition of a settled transaction.IntegrationFault isolationJava

    Options considered

    • rejectedA shared client with per-provider configConfiguration cannot express semantic differences. One provider's success means settled, another's means accepted. That is code, not a config key.
    • chosenAn adapter per provider, owning its own mapping, timeouts and error translationOnboarding the ninth bank requires no reasoning about the first eight, and one misbehaving provider stays contained instead of becoming a platform incident.

    Consequence accepted

    More code, and deliberately so. The duplication buys isolation: per-provider circuit breaking becomes possible, and each adapter declares its provider's semantics in a place an engineer will actually read.

    Grounded in, Led backend development of the FIAP Transfer Service (Java, Spring Boot) across 8+ partner banks.

  2. Model the state you cannot observeNetwork timeouts, missing callbacks and provider-side successes that never reach you are routine at volume, not edge cases.CorrectnessDistributed systemsPayments

    Options considered

    • rejectedTwo outcomes, success and failureForces the system to guess on timeout. A wrong guess in a financial system is worse than no record at all.
    • chosenThree outcomes, with an active resolution path for the thirdThe transaction's lifecycle outlives the request that started it, so something has to own it afterwards: polling, callback handling, reconciliation.

    Consequence accepted

    A transaction is not done when the request returns. That shapes the whole service: status endpoints, bounded polling with backoff, and reconciliation as a first-class feature rather than an operations script.

    Grounded in, Streamlined financial transfer operations across 8+ partner banks; integrated MTN Mobile Money into the B2B middleware.

  3. Split the reporting path from the operational pathTwo very different questions against the same data: “did this customer's payment arrive?” and “how did this biller behave last week?”ArchitectureRead pathsNode.js

    Options considered

    • rejectedOne service, one store, both query typesDifferent latency tolerances and access patterns. The analytical query eventually degrades the operational one, usually under load.
    • chosenA dedicated reporting service alongside the aggregation platformSomeone will run an unbounded query against production data. Better that they do it somewhere that cannot affect a transfer.

    Consequence accepted

    An extra service to operate, and an explicit consistency window between the two paths, which has to be stated rather than discovered by whoever reads the numbers.

    Grounded in, Built and maintained the Biller Aggregation Platform (BAP) and its companion BAP Reporting Service (BRS) in Node.js and Java/Spring Boot.

  4. Serve the model, do not embed itA user-engagement model moving into a live web application, inference now sits in a user-facing request path.Applied MLLatencyTensorFlow Serving

    Options considered

    • rejectedLoad the model in the application processCouples model updates to application deploys, and puts inference memory and latency inside the request-serving process.
    • chosenA serving layer with its own scaling and timeout profileInference becomes an operable dependency: versioned, independently scaled, and with a defined answer to “what does the page do when the model is slow?”

    Consequence accepted

    A network hop and a degraded path to design. The page has to render something useful when inference times out. That is the cost of not having an untestable model inside the app.

    Grounded in, Implemented an ML model to predict user engagement and optimised inference using TensorFlow Serving.

  5. Build the pipeline before splitting the servicesA property platform being decomposed into in-house services, with one engineer owning both the architecture and the deployment.DevOpsCI/CDDocker

    Options considered

    • rejectedSplit first, automate delivery laterServices you cannot deploy separately are a monolith with extra network calls. All of the cost, none of the benefit.
    • chosenContainerise and automate the path to production first, then draw boundariesIndependent deployment is what makes a boundary real. Owning the pipeline also changes how many boundaries you draw, usually fewer, and better ones.

    Consequence accepted

    Slower to the first service, faster to the third. The pipeline is what decides how often a team can safely change its mind.

    Grounded in, Architected in-house backend microservices in PHP and set up CI/CD, Dockerisation and AWS S3 storage for the platform.

How I approach architecture

Four things I hold to

  1. 01

    Boundaries follow what changes together

    Not the org chart, and not a diagram's aesthetics. The useful split is between things that change at different rhythms, because that is what keeps the blast radius of a change proportional to the change.

  2. 02

    Design for the state you cannot observe

    In any system that talks to something it does not control, the interesting state is 'we do not know yet'. Systems that model only success and failure eventually record one of them wrongly.

  3. 03

    A boundary you cannot deploy is not a boundary

    Services that must ship together are a monolith with extra network calls. Owning the pipeline alongside the architecture changes how many boundaries you draw, usually downward, and for the better.

  4. 04

    Someone will ask what happened

    Reconciliation, audit trails and correlation references are not features you add after launch. They are what lets a human establish ground truth when every automated mechanism has been exhausted.

Contact

Let’s Build Something Meaningful

I’m open to senior and lead engineering roles internationally, backend, full-stack, architecture and platform work. The fastest route is email; LinkedIn works just as well.