← About

Career

The summer before my junior year of college, I interned at a small software company building an iOS finance management app — my first real exposure to app development and Xcode. That same year I started working as a road race timer, which introduced me to RunScore, a road-race timing platform originally built in 1985 that was still, decades later, more capable than anything else in the space. It was a good early lesson in what it looks like for software to be built to exactly fit its purpose.

After graduating, I joined C Squared Systems, where I was the sole contributor on a project building scripts for Verizon cell towers to communicate with each other — end-to-end ownership including bug fixes, QA, and direct customer communication. That project gave me my first real taste of full-stack responsibility for a product, and it’s a way of working I’ve sought out ever since.

I moved to PoliteMail a little over a year and a half later, drawn by the growth opportunity, and I’m still there today. My day-to-day stack is React/TypeScript, C#, SQL, and Azure, with C++ and Python where the work calls for it.

Early on, I rebuilt and extended our on-premises customer data import system — customizing data transfer, extending source support, and working closely with Technical Support and customers to handle inconsistent or duplicate data cleanly. From there, I led a full overhaul of our list expansion system, adding Microsoft Graph support alongside our existing Exchange Web Services expansion, and re-architecting the whole flow to run in parallel rather than sequentially. The result was a 10x improvement in expansion speed for customers with large, nested dynamic distribution lists. The bigger lesson from that project was about scope: I built the library to be fully configurable for every possible setup, but most customers just wanted it to work correctly and not worry about configuration. That tension — between what’s technically complete and what the customer actually needs — is something I now weigh explicitly in every design decision.

I was also part of the team that migrated our flagship product from WinForms and ASP.NET to a React and Node stack — rebuilding the UI, separating data access into standalone packages, and splitting the UI from the API layer. I owned the authentication rework as part of that migration, stabilizing token refresh behavior across the new architecture. In the years since, I’ve helped ship template creation, list management, reporting and analytics upgrades, multi-lingual email support, and collaborative editing, while also improving our release process and QA/dev coordination.

The project I’m proudest of is one I led from the ground up: I designed the initial architecture with our CEO and CTO, then led a team of two to five developers through two major phases of a Microsoft Teams application that analyzes sentiment, generates summaries, and buckets discussion topics across a company’s Teams messages, giving leadership visibility into how employees feel about a given topic. The first version ran entirely inside Teams using a locally hosted model and shipped through Microsoft’s App Store review process. Customer feedback pushed us to a second phase: pulling data at the enterprise level instead of per-user, and adding AI-generated summaries alongside the sentiment charts. That meant a new data ingestion pipeline, model hosting on Azure, and a real data privacy layer — encryption in transit and at rest, PII stripping, and restrictions on which conversation types we’d process at all — plus Stripe-based licensing and a demo mode our sales team could use with prospects. Taking that product from a whiteboard conversation to a fully architected, enterprise-ready application was the first time I owned a product end to end. While our first beta customer works through their internal security review, I’ve kept ownership of the project myself, using Claude Code to keep making incremental progress on it alongside my other work.

I’ve also become the go-to person on our team for list expansion, authentication and authorization, content and email template management, and reporting and data processing — the areas where I’ve built the deepest domain knowledge. I’m usually one of the first people pulled into a complex customer issue, and I’ve built enough trust internally that my involvement signals we’ll find the answer, including staying engaged directly with customers until the issue is resolved. I’ve actively asked for more ownership over time — harder customer problems, new development, and mentoring other developers on the team.

Reporting accuracy is one area I’ve gone especially deep on. Customers began seeing open and click rates significantly higher than their historical reports. Digging into the raw data, I traced the inflated numbers to a small number of IP addresses opening and clicking every link in an email within a cadence no human could replicate — several links clicked within milliseconds of each other, shortly after send — a different pattern than the automated iOS Mail proxy opens I’d identified and filtered out previously. Grouping the open/click/send data together, I traced the IPs to known ASN ranges owned by large enterprises, and confirmed with the customer that it matched an internal security system scanning all links and images on receipt. I extended our proxy detection to recognize known scanner ranges, gave customer admins the ability to add their own ranges as new scanners appeared, and built a re-run feature so techs could retroactively clear proxy interactions out of existing reports. Rolling that out to our largest customers — backed by detailed, evidence-based explanations of exactly what was happening in their data — rebuilt trust in report accuracy broadly enough that we featured the fix in a product newsletter. I’ve done similar work on the infrastructure side: when a customer’s database grew large enough to push report processing into SQL timeouts, I added indexing at key bottlenecks and built a caching layer between our core write tables and report aggregation, so reports could run off a smaller, controlled dataset instead of the full growing tables — eliminating the timeouts without requiring the customer to change their configuration. Between these and dozens of smaller fixes, reporting accuracy is the domain where customers and our own tech team trust my read on the data without needing to double-check it.