What I have been responsible for inside other companies products, organised by the system rather than by the job. The dated table is on the résumé. My own product work is under projects.
Senior Software Engineer · Mindful, then Medallia · remote, US
Jan 2022 to now
A real time IVR survey platform running millions of surveys a day. I joined it on contract on a live codebase and now own its architecture and delivery.
Medallia acquired Mindful in August 2022. I stayed with the product, so this is one continuous piece of work across two employers rather than two jobs.
Where it sat
Mindful Feedback collects customer feedback at the end of a contact centre interaction, mostly over the phone as an IVR survey. It runs millions of surveys a day for enterprise customers, and it speaks to the platforms those customers already run their contact centres on: Genesys Cloud, Twilio Flex, Zendesk and Salesforce. I did not start it. I joined Mindful on contract in January 2022, into a codebase that was already live, already integrated and already earning, and the scope grew from features to owning the platform.
Scale
Volume
Millions of surveys a day
Environments
Six, one isolated US only region
Compliance
SOC 2
Team
Five person external vendor team
What I was responsible for
Architecture and delivery
I own the architecture and delivery of the platform. That covers where new behaviour belongs, what goes into a release, and how a change reaches six production environments, one of them an isolated United States only region for data sovereignty, all under SOC 2. The regulatory surface is not a side constraint on that work. It is the reason the delivery path looks the way it does.
Enterprise CCaaS integrations
Every contact centre platform has its own idea of what a conversation is and when it has ended. Genesys Cloud, Twilio Flex, Zendesk and Salesforce disagree about the shape of a call, the moment a survey may fire, and what is available to attach to it, and on top of that each enterprise customer wants different questions, different routing and different retention. The platform answers that with a database driven configuration layer, with per client feature flags and workflow customisation, so what a platform is and how a client differs are data rather than code. I did not invent that layer. My job has been to keep choosing it: when a customer wants behaviour the configuration model cannot express, extend the model rather than add a client specific branch behind it, even when the branch is the cheaper fix in front of me. What that buys is the fifth and sixth integration staying as cheap as the second.
The Experience Management System pipeline
After the acquisition I built the one way pipeline from the Laravel codebase into Medallia’s fifteen year old Experience Management System, which is an accumulation of microservices where survey responses land on enum based field definitions that convert into binary storage. Ingestion is fault tolerant polling on Laravel job queues with automatic retry. That integration secured a multi-million dollar enterprise contract.
The front end migration
I led the migration off Vue, jQuery and Blade onto React. Three front end idioms in one product is three ways to answer every question, and the cost of that is paid by whoever arrives next rather than by whoever wrote it.
Codebase health
My first year was core feature work on the enterprise IVR platform, API performance work, and pulling a controller heavy monolith apart into service oriented code under PHPUnit and Pest, test first. That mattered more than it looked: a configuration driven platform is only as trustworthy as the code reading the configuration, and the refactoring is what made the layer something you could reason about rather than something you hoped about.
Mentoring and a vendor team
Mentoring on the team, and running a five person external vendor team. A vendor team works from what is written down, so the documentation and the contracts around a change became part of my output rather than an afterthought to it.
The bit that was not obvious
Automatic retry on a job queue is at least once delivery, and at least once delivery is only safe when the thing you are writing to can recognise a repeat. A survey response is not a harmless duplicate. It is a second opinion from a customer who only had one, and once it has been mapped through the enum definitions into binary storage there is no natural key left to deduplicate against downstream. So the retry safety had to be established on our side, before the write, and the mapping had to be treated as a lossy one way door rather than a transform you can reverse and reconcile later. A mid level engineer turns on the retry, sees the pipeline survive a failure injection, and calls the job done. The work that actually mattered was deciding what identity a response carries into a system that was never designed to be asked.
Stack
Laravel
PHP
React
Vue
Blade
MySQL
Redis
AWS
GitHub Actions
REST
PHPUnit
Pest
Autopilot Print and Printicular
Software Engineer, then Engineering Team Lead · MEA Mobile · Hamilton, NZ
Aug 2019 to Jan 2022
Photo printing at 5 to 30 orders a minute into retail fulfilment. I owned the catalogue integration, the admin panel and the API contract three client apps were built against, then led the backend team.
Where it sat
Autopilot Print and Printicular take photos from a phone or a browser and turn them into a physical print waiting at a retail counter. The platform ran at 5 to 30 orders a minute, feeding multiple white labelled web apps served globally from CloudFront and S3 edge locations, with fulfilment partners including Walgreens, Target, Warehouse Stationery and Ted’s Cameras. It was a mature product long before I got there. I joined in 2019 as a Software Engineer and led the backend team from mid 2021. A print order is also a physical object: once a lab prints it, a wrong paper size or a wrong crop is a wrong product in a customer’s hands, and the failure mode is not an exception in a log, it is a courier.
Scale
Throughput
5 to 30 orders a minute
Delivery
CloudFront and S3 edge locations, global
Clients
iOS, Android and static web on one contract
What I was responsible for
The FedEx catalogue integration
An SDK that polled their API on a schedule for products, specifications and pricing, instead of a local copy maintained by hand. The cost I accepted is that the catalogue is eventually consistent, so there is a window where our idea of a price and the retailer’s idea differ. That window is small, bounded and visible, which a hand maintained copy never is.
The Laravel admin panel
The single CRUD surface for SKUs, retailer specific print specs, client configuration, feature flags and API credentials for every fulfilment partner, so the answer to what a given retailer will actually print lived in one place rather than spread across five. An admin panel that owns everything becomes an operational single point of risk, so it has to be permissioned and audited properly rather than left as the convenient back door it wants to be.
The JSON API
One contract serving iOS, Android and the static web builds, rather than an endpoint per platform. Endpoint specifications went to the mobile teams ahead of their sprints, before the endpoints existed.
Leading the backend team
From June 2021 I led the backend team on both products. Adding a fulfilment partner touches the catalogue, the specs, the credentials and three client apps on three release cadences at once, so most of the lead work was sequencing that so nobody waited on a change they could have been told about a week earlier.
The web app builder migration
I assisted on the migration of the custom web app builder from PHP to React and Gatsby with Chakra UI, generating static storefronts from JSON API configuration. Assisted is the accurate word. The migration was not mine.
The bit that was not obvious
Publishing the endpoint specifications before the endpoints existed sounds like a scheduling detail and it is really a decision about what the API is. With three clients on separate release cadences, the JSON API is not something the backend produces and the clients consume when it is ready. The contract is the product, and the implementation behind it is an implementation detail. The obvious way to work is to build the endpoint, then hand it over, and that leaves three client teams sitting behind one backend team’s sprint, each discovering a different disagreement about the shape of a response in a different week. Publishing the contract first turned those teams from sequential to parallel, and moved every argument about field names, nullability and error shapes to the cheapest possible moment, which is before anyone has written code that depends on the answer. The cost is that you have to be willing to be held to a document you wrote before you knew everything, and to version it honestly when you were wrong about it.
Stack
Laravel
PHP
React
Gatsby
Chakra UI
MySQL
AWS
CloudFront
S3
JSON:API
The client portal
SEO Specialist and Software Engineer · NetValue · Hamilton, NZ
Jun 2018 to Aug 2019
A Laravel portal that automated SEO reporting and took more than ten hours of manual work a week out of the agency.
Where it sat
NetValue is an agency, so the work came in two halves that most people keep apart. I held the SEO specialist half and the engineering half of the same accounts, which is the reason the portal was mine to build: I was the person doing the reporting by hand, so I knew exactly which part of it was work and which part was transcription.
Scale
Recovered
More than ten hours a week
What I was responsible for
The Laravel client portal
It pulled SEMrush metrics and parsed inbound report emails onto the right client account. That removed more than ten hours of manual work a week and turned billable admin into margin. The parsing is the part worth noting: the reports already existed and already arrived, so the cheapest place to automate was the inbox rather than a new integration nobody had agreed to pay for.
Client web apps
Delivery on a custom Zend based PHP framework, WordPress and SilverStripe. Three stacks across one client list, chosen before I arrived, which is the normal condition of agency work rather than a problem to be solved.
The SEO practice
The specialist half of the role. It is the reason the reporting problem was visible to me as an engineering problem at all.
Stack
Laravel
PHP
Zend
WordPress
SilverStripe
SEMrush
Moviko Creative
Co-founder · Moviko Creative · Hamilton, NZ
Mar 2016 to Sep 2017
Ran a web agency with two others, and did the technical execution on its builds.
Overlaps the Vision College entry below on purpose. I was tutoring while running the agency.
Where it sat
Three of us ran it. That size means there is no one to hand anything to, so the work was whatever the week needed: finding the client, agreeing what we were building, building it, and getting paid for it.
What I was responsible for
Client acquisition and delivery
Finding the work and then being accountable for it landing. Running a small agency is where I learned what a scope conversation is actually for, which is deciding what is not being built.
Technical execution
The Laravel and WordPress builds were mine to execute.
Stack
Laravel
PHP
WordPress
Web development curriculum
Web Design and Development Tutor · Vision College NZ · Hamilton, NZ
Jan 2017 to Jul 2017
Wrote and taught the web development curriculum, and co-wrote an NZQA accredited IT operations course.
Where it sat
Teaching a room of twenty or more people is the fastest way to find out which parts of what you know are actually explainable and which parts you have only been getting away with. It is the closest thing to code review at volume.
What I was responsible for
The curriculum
I wrote the web development curriculum and taught it to classes of twenty or more.
NZQA accreditation
Co-wrote an NZQA accredited IT operations course, delivered across campuses. Writing to an accreditation standard is a documentation discipline, and it is the same discipline that a vendor team or an audit asks for later.
Stack
Curriculum design
NZQA accreditation
Freelance and the early years
Freelance developer · Freelance · remote, NZ
Jan 2011 to Jan 2016
Web and eCommerce work for clients worldwide, and a gaming server community of 100 daily players built on custom game modes.
Where it sat
Five years of being the whole team. Every part of a project, from the conversation that starts it to the server it ends up on, was mine by default, which is where the habit of owning a domain end to end comes from.
What I was responsible for
Client work
Web and eCommerce builds for clients worldwide.
A gaming community
I built and ran a server community of 100 daily players on custom Pawn game modes. Running a live service for people who notice the moment it is down, at an age when nobody was paying me to care, taught me more about operations than any course I took afterwards.