[{"data":1,"prerenderedAt":186},["ShallowReactive",2],{"navigation":3,"page-\u002Fwork":16},[4,8,12],{"title":5,"path":6,"stem":7},"About","\u002F","1.index",{"title":9,"path":10,"stem":11},"Work","\u002Fwork","2.work",{"title":13,"path":14,"stem":15},"Open Source","\u002Fopen-source","3.open-source",{"id":17,"title":9,"body":18,"description":180,"extension":181,"meta":182,"navigation":183,"path":10,"seo":184,"stem":11,"__hash__":185},"pages\u002F2.work.md",{"type":19,"value":20,"toc":168},"minimark",[21,25,38,43,46,54,57,60,69,73,76,79,82,86,89,92,105,109,112,115,118,122,125,128,132,135,138,141,145,148,151,155,158,161],[22,23,9],"h1",{"id":24},"work",[26,27,28,29,37],"p",{},"I'm Lead Engineer at ",[30,31,36],"a",{"href":32,"rel":33},"https:\u002F\u002Fhappydog.digital",[34,35],"noopener","noreferrer","Happy Dog",", setting technical direction across more than forty production applications. The sections below are organized by capability rather than by client. Some of those clients are named because they have published the work themselves; the rest are not, so their engagements are described without them.",[39,40,42],"h2",{"id":41},"backend-platform-engineering","Backend platform engineering",[26,44,45],{},"Symfony with a particular focus on Sylius e-commerce, Laravel, and Go, with PHP going back to 2010.",[26,47,48,53],{},[30,49,52],{"href":50,"rel":51},"https:\u002F\u002Fhappydog.digital\u002Fcase-studies\u002Fgrafe-auction",[34,35],"Grafe Auction"," runs a custom online auction platform we built to replace three third-party packages that had been stitched together. The constraint that makes it interesting is the live auction. An online bidding system that only has to serve its own web clients is a well-understood problem; this one has to stay in step with an auctioneer standing in a room calling lots as they happen, across multiple rings running at the same time, while taking pre-bids, live bids and max bids and settling the invoicing once the hammer falls. Before the platform existed, the link between the room and the website was a person with an earpiece standing next to the auctioneer, on a phone call to somebody operating the online side. That person is gone: the platform speaks to the auctioneer directly, in microseconds, through text to speech. Staff load inventory in bulk by the thousands, and catalog items from a mobile application while they photograph them.",[26,55,56],{},"Another long-running engagement is a Sylius storefront we built from scratch and have grown since. Much of what we have built there is a pricing system rather than a catalog: products priced in tiers, and shipping quoted through a tiered calculator the customer works through at checkout, with both sides having to agree on the same order.",[26,58,59],{},"Shipping started from two problems at once. Rate lookups came back wrong, and the quotes were wrong even when a lookup succeeded, because the products are bulky and awkwardly dimensioned and nothing in the stock calculation knew how they actually pack. Sylius' shipping calculator interface is built around fixed rates and does not extend comfortably to dynamic ones, so quoting against carriers in real time meant building that path rather than configuring it, and I architected a shipping dimension matrix that encodes how the inventory packs. Rates that come back are persisted rather than discarded, so staff can see afterwards which ones were returned and why one was selected. A customer now either gets a quote that reflects what the shipment will actually cost, or is told up front that their order cannot be quoted online rather than being handed a number that will not hold, and the client quotes against real cost instead of absorbing the difference after the fact.",[26,61,62,63,68],{},"For ",[30,64,67],{"href":65,"rel":66},"https:\u002F\u002Fhappydog.digital\u002Fcase-studies\u002Fmbe",[34,35],"MBE",", a trucking brokerage, we replaced a Microsoft Access setup and desktop-only software with a Laravel application their staff reach from anywhere, and the reports that used to take hours now finish in under a minute.",[39,70,72],{"id":71},"infrastructure-and-platform-operations","Infrastructure and platform operations",[26,74,75],{},"I've led a long-running modernization of a client platform running on Google Cloud Platform with its application fleet on Kubernetes: moving static asset traffic onto a CDN, putting a web application firewall in front of it and tuning the OWASP core rule set across staging and production, and standing up service-level objectives with alerting attached to them.",[26,77,78],{},"Alongside it, container and build engineering across the same fleet — multi-stage image builds, build-cache configuration, image-size reduction, and continuous integration cost and runtime.",[26,80,81],{},"On another engagement I containerized a Symfony and Sylius application that had been running on cPanel-style shared hosting and moved it onto a managed platform, with the environment expressed as infrastructure as code rather than assembled by hand. Per-service configuration is committed to the repository instead of being set in a dashboard, and the infrastructure documentation sits alongside it, so the environment can be stood up again from the repo rather than reconstructed from memory.",[39,83,85],{"id":84},"data-and-migration-architecture","Data and migration architecture",[26,87,88],{},"The largest of these is a coordinated platform migration from a monolithic application to a decoupled service stack, with a Nuxt frontend now in place. Running the old and new stacks side by side for the length of a migration like that is a real cost to carry, and a smaller one than a single cutover would have been.",[26,90,91],{},"Others:",[93,94,95,99,102],"ul",{},[96,97,98],"li",{},"Microsoft Access to MySQL and Cloud SQL for the trucking brokerage, without interrupting a day of work.",[96,100,101],{},"A Joomla application with a stack of components bolted onto it, rebuilt on Symfony and Sylius, and maintained and extended since.",[96,103,104],{},"MariaDB to MySQL 8 across engines, which turned out to have gone through an interim hop rather than in one step. Finding that the real lineage differed from the documented plan changed how the final cutover was sequenced.",[39,106,108],{"id":107},"resilience-and-incident-response","Resilience and incident response",[26,110,111],{},"Deliberate maintenance windows, rather than deploys that leave a system half up: fleet-wide state that pauses background workers, refuses new realtime connections, and lets operators through with a signed bypass, so the state of the platform during a window is something you declared rather than something you infer.",[26,113,114],{},"Dependency decisions get made against the tree rather than the changelog. Whether a newer version exists matters less than what is holding the current one in place, what upgrading drags forward with it, and whether that constraint is worth breaking now or worth living with for a while. When the answer is to stay put, it gets written down with the reason and the condition that would change it, so the next person to look does not have to work it out again.",[26,116,117],{},"Incidents happen, and over the years some have been serious. They were handled with care and turned into checks that would catch a recurrence. The specifics belong to the clients.",[39,119,121],{"id":120},"observability","Observability",[26,123,124],{},"Distributed tracing across six runtimes — Symfony, Go, Python, Flutter, nginx, and a document-rendering service — with per-service error tracking, so a failure lands in the project that owns it instead of a shared bucket. Most of the work is in getting trace context to propagate between them, since every SDK matches trace targets slightly differently.",[26,126,127],{},"Metrics go through the hosting platform's own monitoring stack, and logs are structured JSON written to stdout and collected by the platform's logging agent rather than shipped from inside the application.",[39,129,131],{"id":130},"mobile-platforms","Mobile platforms",[26,133,134],{},"Native iOS and Android for a client's field applications, and Flutter work on the application Grafe's staff use to catalog inventory.",[26,136,137],{},"Deployment-target minimums on the native applications are set from adoption data rather than from what the newest platform APIs would allow. Raising a minimum OS version drops some share of the people already using the application, so a proposed increase starts as a data-gathering exercise against the crash reporter's OS distribution and the server logs, and the decision that follows is a business one made with numbers in front of it.",[26,139,140],{},"Both applications have been through a deliberate internal audit and improvement cycle: findings triaged by severity, worked in that order, and the ones consciously deferred recorded as deferred rather than quietly dropped. That work moved credentials into platform secure storage on both platforms, reduced the backup and permission surface, and replaced bundled third-party libraries with platform equivalents.",[39,142,144],{"id":143},"ai-and-llm-systems","AI and LLM systems",[26,146,147],{},"A retrieval-augmented assistant over production data, built with LangChain and traced with Langfuse, using an embedding client I wrote once the framework's own path stopped fitting what we needed. A separate service produces sales predictions, written from scratch after a managed-model approach turned out not to tune efficiently enough to be worth keeping.",[26,149,150],{},"A model that writes SQL against a production database can read whatever its connection can read. This one queries through restricted views rather than base tables, so what a bad generation can reach is bounded by the view rather than by the schema, which is not something instructions in a prompt can guarantee.",[39,152,154],{"id":153},"technical-leadership","Technical leadership",[26,156,157],{},"Setting technical direction across more than forty applications means most of the leverage is in decisions I do not implement myself: which constraints are real, what gets rewritten and what gets left alone, and when the right answer to a client request is to talk them out of it. I work as the senior technical voice between Happy Dog and the client organizations, which is as much translation as it is engineering.",[26,159,160],{},"That started in the Army. As a Data Support Team Chief I led the team responsible for the deployable network infrastructure a unit takes into the field, and as a Sergeant I was responsible for the morale, welfare, and professional development of the junior Soldiers on it.",[26,162,163,164,167],{},"Open source accounts for the rest of this, and has ",[30,165,166],{"href":14},"its own page",".",{"title":169,"searchDepth":170,"depth":170,"links":171},"",2,[172,173,174,175,176,177,178,179],{"id":41,"depth":170,"text":42},{"id":71,"depth":170,"text":72},{"id":84,"depth":170,"text":85},{"id":107,"depth":170,"text":108},{"id":120,"depth":170,"text":121},{"id":130,"depth":170,"text":131},{"id":143,"depth":170,"text":144},{"id":153,"depth":170,"text":154},"Backend platform engineering, cloud infrastructure, data migration, resilience, observability, mobile, and LLM systems, with the engagements behind each.","md",{"numberedSections":183},true,{"title":9,"description":180},"_AEo04uvFTBCai4-_dRFMk8eIZ6hfkko19bExgfq6KU",1787768014282]