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.
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.
Clients
- Web applicationBrowser
- Mobile applicationReact Native · iOS + Android
Edge
- API surfaceRouting · Auth · Rate limiting
Services
- ListingsPHP
- Tenancy & operationsPHP
- Engagement inferenceTensorFlow Serving
State
- Relational storeTransactional data
- CacheHot reads
- Object storageAWS S3 · media
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.
Consumers
- B2B middlewarePlatform callers
- Internal servicesServer-to-server
External providers
- Partner bank adapters8+ institutions
- Mobile moneyMTN MoMo API
- Settlement & reconciliationAsynchronous
- Transaction ledgerSystem of record
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.
Consumers
- Agent applicationsRetail channel
- B2B middlewarePartner callers
- Support portalLaravel
External providers
- Airtime & dataInstant settlement
- ElectricityToken delivery
- Betting walletsWallet top-up
- Reporting serviceBRS · audit trail
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.
Sources
- Driver applicationKotlin · Android
- Third-party trackingProvider APIs
- IoT telemetryVehicle signals
Processing
- NormalisationOne event shape
- Position & statusCurrent state
Platform
- Freight managementLaravel
- Dynamic routingRoute adjustment
Consumers
- Operations consoleDispatch
- Customer visibilityDelivery status
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.
Intake
- Financial documentsUnstructured input
Extraction
- NLP pipelinePython
- Structured fieldsNormalised output
Control
- Human reviewApproval gate
System of record
- Compliance backendAuthoritative store
- ReportingProgramme oversight
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.
- 01CommitVersion control
- 02Build & testAutomated checks
- 03Container imageDocker
- 04DeployPer-service release
- 05VerifyHealth & rollback path
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.
Clients
Edge
Services
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.
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.
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.
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.
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.
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.
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.
Four things I hold to
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.
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.
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.
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.