Notes on Building, Leading, and Figuring Things Out

Lessons from 15 years in tax tech, building AI tooling, and leading teams through impossible-sounding projects.

August 2026 6 min read

My Son Asked Me Why I Was Staring at My Phone During His Game

He didn't ask it to guilt me. He asked it the way a seven-year-old asks why the sky is blue — like the answer was going to be genuinely interesting. It wasn't. And that's what broke me.

The Setup

Third base. My kid is playing third base in a rec league game in northern Virginia on a Saturday morning that smells like cut grass and someone else's sunscreen. I have my phone out because a deploy went sideways Friday night and I'm watching a Slack thread about a Lambda timeout that may or may not be resolved, depending on who you believe.

He catches a grounder. Throws to first. Gets the out. Turns around looking for me. And I'm looking at a thread where two engineers are arguing about whether the fix is idempotent.

He doesn't say anything then. He finds my face eventually, I give him the thumbs up, and we move on. But in the car afterward, with his cleats still muddy and his hat on sideways, he asks: "Why were you looking at your phone during my game?"

The Answer I Gave vs. The Answer That Was True

I said something about work, something important came up, I'm sorry. He accepted it the way kids accept things — completely, on the surface, while storing it somewhere you can't reach.

The true answer is worse: nothing that was in that Slack thread required me in that moment. The engineers had it. The incident was contained. I was reading it because I have spent fifteen years training myself to believe that being informed is the same as being useful, and that being useful is the same as being present, and somewhere in that chain of logic I convinced myself that checking a thread during a youth baseball game was a form of responsibility.

It isn't. It's a habit wearing responsibility's clothes.

The Part Where I Don't Pretend I Fixed It

I'm not going to tell you I put my phone in the glovebox for every game after that. I didn't. I'm still fighting this. Some Saturdays I'm fully there. Some Saturdays I catch myself mid-scroll in the second inning and feel the specific shame of a person who knows exactly what they're doing wrong and does it anyway.

What I will tell you is that his question rewired something. Not because it was accusatory — he's seven, he was curious — but because it exposed the gap between the story I was telling myself ("I'm managing a critical system") and the story anyone watching me would tell ("that guy is missing his kid's game to read text messages").

The gap between how we narrate our own choices and how those choices actually look from three feet away is where most of fatherhood goes wrong.

What Engineering Culture Actually Does to You

Here's the thing nobody says out loud: technical leadership selects for a specific kind of anxiety. The job rewards the people who feel responsible for things even when they're not on call. The ones who check the dashboards on vacation. Who feel a low-grade dread when they're unreachable. This trait is genuinely useful in the office. It builds reliable systems. It catches problems early.

It is a disaster in a little league stands.

I built a code intelligence platform in six days because I can focus completely when the problem is in front of me. I can be obsessive and efficient and relentless. But that same wiring — the one that won't let a problem exist unattended — doesn't turn off when I walk onto the grass. It just finds new things to attend to. And the new things are always on the phone, because the phone is always there.

The Actual Discipline

People talk about "being present" like it's a mindset shift. It's not. It's a physical intervention. The phone has to not be in your hand. That's it. That's the whole discipline.

I've started leaving it in the car for the first half of whatever we're doing. Not forever. Not with some ceremonial speech about it. Just — in the car. If something burns down, someone will call. If they call and I don't answer, they'll call again. I have a fifteen-person engineering team. They are capable. I hired them specifically because they are capable. Treating every weekend notification like it requires my personal touch is not leadership. It is ego dressed as diligence.

What He Actually Needs

My son doesn't need a father who has achieved perfect work-life balance as described in a LinkedIn post. He needs a father who shows up to things and watches them. Who knows which kid on his team throws with his left hand. Who remembers that he switched from batting fifth to batting second and has opinions about it.

He needs me to be a person in his life, not a person adjacent to his life who is also managing infrastructure.

The dirty secret is that he's teaching me something I apparently couldn't learn from fifteen years of shipped software: that the systems you build for people you love don't have dashboards. You don't get a metric that tells you you're doing well. You just have to show up, watch the grounder, and know when to put the damn phone down.

Third Base

He's playing shortstop now. They moved him this season. He's better there — more range, quicker release. I know this because I watched it happen across four games in a row where my phone stayed in my jacket pocket.

He still checks for my face when he makes a play. I'm still working on making sure it's worth finding.

Key Takeaways

  • The habit of staying informed is not the same as being useful — and it's definitely not the same as being present.
  • Technical leadership wires you for a specific anxiety that is an asset at work and a liability on a Saturday morning at a baseball field.
  • "Being present" is a physical intervention, not a mindset. The phone has to not be in your hand.
  • Your kid doesn't need you to have it all figured out. They need your face to be the one that's actually watching.
August 2026 6 min read

Everyone Thinks They're the Customer

The tax industry has a customer problem nobody talks about openly: there are four of them, they want opposite things, and exactly one of them actually pays you. Building software in this space means quietly choosing sides every single day.

The Actual Problem

Most software has a customer. Maybe two. You build for the person who pays you, you watch the metrics, you ship. Clean feedback loop. The tax industry has a different structure that I didn't fully understand until I was three years deep into it: the taxpayer, the preparer, the employer or financial institution generating the data, and the IRS all behave like they are your customer. They have competing requirements, incompatible definitions of success, and zero interest in each other's constraints.

The taxpayer wants it to be free, fast, and to tell them they're getting a refund. The preparer wants accuracy, audit defense, and a pricing model that isn't race-to-the-bottom. The W-2 sender wants their file format accepted without drama. The IRS wants schema compliance and rejects anything that deviates by a single byte from a spec document that was last updated in a format only readable in Internet Explorer. Every product decision you make implicitly ranks these people. Almost nobody admits it out loud.

The Preparer Is the Most Underserved Person in the Ecosystem

I'll say something that sounds obvious but apparently isn't: professional tax preparers — the CPAs, the enrolled agents, the solo practitioners doing 400 returns a year out of a strip mall office in Roanoke — are the closest thing to a power user this industry produces, and the software mostly treats them like a liability. The UX assumes they need hand-holding. The workflows assume they'll have a W-2 in hand rather than a client who emails a photo of it three days before the deadline. The error messages read like they were written by a lawyer to protect the software company, not help the preparer understand what went wrong.

I've watched experienced preparers develop genuinely impressive workarounds. Custom spreadsheets that pre-validate data before it goes into the actual system. Printed checklists that exist because the software doesn't surface the right questions in the right order. Keyboard shortcut muscle memory that compensates for UI flows nobody ever asked them about. That's not users finding creative solutions. That's users patching holes.

The Taxpayer Relationship Is Stranger Than It Looks

Consumer tax software has one of the weirder relationships in any product category. People use it once a year, under mild-to-moderate stress, for a task they find either boring or terrifying, with data they don't fully understand, to produce a document they're legally required to file accurately but also can't easily verify. Then they leave and come back next year having forgotten everything.

The UX challenge isn't really about UX. It's about trust under low-information conditions. Someone is telling your software things about their life — their kid's social security number, their side income they feel weird about, the home office they might be stretching the definition of — and they need to believe the software is handling it correctly without being able to independently confirm that. The free-file wars and the refund-advance products exist in that trust gap. It's not pretty.

Every year the industry reruns the same debate about simplification. Every year the tax code adds seventeen new edge cases. Every year the software ships.

What Employer Data Actually Looks Like

Here's something that doesn't get discussed enough outside of engineering rooms: a non-trivial percentage of the W-2s, 1099s, and other third-party data that flow into tax software are wrong. Not fraudulently wrong. Just wrong. Transposed numbers, truncated employer names, box amounts that don't reconcile with what the taxpayer actually received, SSNs with a single digit off. The IRS matching process will eventually find some of these. The preparer is supposed to catch others. The consumer is supposed to catch the rest, which requires knowing what the document is supposed to say, which most people don't.

So you build validation logic. You add heuristics. You flag things that look statistically unlikely. And then you have to decide: do you stop the user and make them confirm, knowing that confirmation bias means they'll click through it, or do you let it pass and hope the real error surfaces in the match process months later? Neither answer is good. You pick the one that generates fewer support calls and live with it.

The IRS as Architectural Constraint

I've worked with a lot of external dependencies in fifteen years of engineering. Government APIs are their own category. IRS systems are old in a specific way — not charmingly vintage, but load-bearing-legacy old, where the thing that seems like a quirk is actually the structural element the whole system rests on. You don't fix it. You learn its weight distribution and you build around it.

Modern tax software engineering is substantially an exercise in translating between what the world looks like in 2025 and what the submission infrastructure was designed to handle in a prior decade. That's not a complaint. It's just the terrain. The interesting engineering problems live in that translation layer — how do you make something feel fast and intelligent on top of something that is neither? How do you surface actionable information to users when the authoritative source processes in batch with a 48-hour lag?

The Business Model Problem Nobody Fixed

The consumer tax software market has a free tier problem that's been festering for a decade. Free file agreements, competitive pressure, and the political impossibility of charging lower-income filers directly have produced a situation where the revenue model increasingly depends on upsells, audit protection products, and the people just complicated enough to need a paid tier but not complicated enough to hire a CPA. That is a narrow band. It gets narrower every year that the IRS improves its own direct-file infrastructure.

Professional software has different economics but its own version of the problem: pricing power in a market where the large players can afford to compress margins to protect market share, and the small players are one bad tax season away from consolidation. There are fewer independent tax software companies than there were ten years ago. That trend doesn't reverse on its own.

Why I Still Find It Interesting

I've been in this industry long enough that people occasionally ask why I haven't moved somewhere with faster growth or cleaner technical problems. The honest answer is that the constraints are the interesting part. You're not building in a greenfield. You're building something that has to be right — not approximately right, not right-enough-for-v1 — because the cost of wrong is a federal penalty for a real person. That sharpens thinking in ways that optional software doesn't.

Plus the seasonality means every year you get a hard deadline and a concrete measure of whether what you built held up. Filing season is a production load test you can't opt out of. There's something clarifying about that. I'll take clarifying over comfortable most days.

Key Takeaways

  • The tax industry serves four incompatible 'customers' simultaneously — every product decision is implicitly a ranking of them, whether you admit it or not.
  • Professional preparers are the closest thing to power users in the space and are systematically underserved by software that treats their expertise as a liability.
  • A significant share of third-party tax data is quietly wrong, and the decision of how aggressively to surface that to users is one of the industry's least-discussed design problems.
  • The business model constraint is structural, not fixable by better UX — the revenue band is narrowing and the IRS building its own tooling accelerates that.
August 2026 6 min read

The Last Industry That Still Treats a PDF as a Data Format

The tax industry moves billions of dollars a year and still treats scanned PDFs as a primary data interchange format. This is not a technology problem. It's a power problem — and understanding who benefits from the mess explains why it never gets fixed.

Let Me Describe a Real Data Pipeline

A payroll processor generates W-2 data from a database. They export it to a PDF. They mail that PDF — sometimes physically, sometimes digitally — to a taxpayer. The taxpayer hands it to a tax preparer, who either manually keys the numbers or runs it through OCR that gets the state withholding wrong about 4% of the time. The preparer's software packages everything back into structured XML, encrypts it, and transmits it to the IRS. The IRS parses that XML back into a database.

So we went: database → PDF → human eyeballs → OCR → XML → database. In 2025. For a transaction that has maybe twelve fields. This is not an edge case. This is the industry's core data flow for roughly 160 million filers.

The Easy Explanation Is Wrong

Most people who hear this story blame legacy systems, or regulatory inertia, or the general technological conservatism of financial services. Those things exist, but they're not actually the reason. The IRS has had a structured electronic filing mandate since the 1990s. The SSA can receive W-2 data electronically. The infrastructure for direct employer-to-IRS data sharing exists and has existed for a long time.

The PDF lives because removing it would shift power. Specifically, it would shift power away from intermediaries — payroll processors, large employers, and, frankly, the tax prep industry itself — and toward either the government or the taxpayer directly. The complexity is the product. The friction is the moat.

Who Actually Owns Your Tax Data

Here's a question most people have never asked: who owns the structured data in your W-2? Not the paper form — the actual wage and withholding figures that your employer reported. Your employer reported those numbers to the SSA. The SSA shares them with the IRS. The IRS has them. They have had them for months before you file.

In Denmark, you get a pre-filled return. You review it, correct anything wrong, and submit. The whole thing takes about fifteen minutes and is done on a government website. The Danish tax authority does this because it can — because the data flows directly from payroll systems to the state, without a PDF detour through your kitchen table.

We don't do this in the United States. There are many stated reasons. Some of them are even legitimate. But the loudest opposition to return-free filing every time it surfaces in Congress comes from the commercial tax prep industry, which collects somewhere between $11 billion and $13 billion a year from Americans filing returns that, in a large fraction of cases, could be filed automatically. That's not a conspiracy theory. That's a lobbying disclosure form.

The PDF is not a technical artifact. It's a business model preserved in file format.

What This Looks Like From Inside the Industry

I want to be fair here, because I work in this industry and I'm not trying to pretend I'm standing outside it throwing rocks. The companies I've worked at and with employ a lot of engineers who are genuinely trying to make tax filing less painful. The product teams care about reducing errors. The customer support people are dealing with real human stress every February when someone can't figure out if their 1099-G counts as income.

But the structural incentive of the commercial tax software space is not to make taxes easy. It's to make taxes survivable with our help. There's a difference. An industry that makes taxes easy competes itself out of existence. An industry that makes taxes survivable — that guides you through complexity, that translates the chaos into something you can submit — that industry has a durable reason to exist. So when I see product decisions that add guidance rather than remove steps, I understand the logic even when I find it frustrating.

The AI Angle Is More Complicated Than People Think

Right now there's enormous excitement in this space about AI. Large language models that can answer tax questions, agents that can navigate IRS forms, tools that can extract structured data from — you guessed it — PDFs. I build some of this stuff. I think some of it is genuinely useful.

But I also notice that most of the AI investment in tax is going toward making the current broken pipeline smarter, not toward questioning why the pipeline is broken. Better OCR for your W-2 PDF is a real improvement. It is not the same as asking why you have a PDF instead of an API call. We're getting very good at automating the workaround.

The Reform That's Actually Possible

I don't think return-free filing is coming to the United States in the next decade. The political economy is too entrenched and the edge cases are legitimately hard — gig economy income, multiple jobs, investment activity, home sales. A pre-filled return works cleanly for a W-2 employee with one job and no other income. It gets complicated fast.

What I do think is possible: mandatory machine-readable form delivery. If you are an employer or financial institution required to issue a 1099 or W-2, you should be required to make that data available in structured form to the recipient, not just as a PDF. Not to the IRS directly — to the taxpayer, in a format their software can ingest without OCR. This is a small change. It removes one human transcription step. It doesn't threaten the commercial prep industry because you still need someone to aggregate it and do the actual return. It just makes the pipeline less stupid.

It would probably save several hundred million dollars a year in aggregate error costs and prep time. Nobody in a position to mandate it seems particularly motivated. Make of that what you will.

Why I'm Still Here

Fifteen years is a long time to work in an industry with this much structural dysfunction. People ask me about it occasionally and I usually say something about the problem being genuinely hard, which is true. Tax law is legitimately complex. The intersection of fifty state regimes with the federal code with international reporting requirements with the gig economy with cryptocurrency with whatever Congress did in the last reconciliation bill is a real engineering challenge regardless of how the data flows.

But honestly, the other reason is that the gap between what this industry is and what it could be is enormous, and enormous gaps are where interesting work happens. The PDF is still winning right now. That means there's still a real fight left to have.

Key Takeaways

  • The tax industry's reliance on PDFs as a data format is a power structure, not a technical limitation — intermediaries profit from the friction they help navigate.
  • The IRS already has most of your tax data before you file; the reason you still file manually is political economy, not technical impossibility.
  • Most AI investment in tax is making the broken pipeline smarter rather than questioning why the pipeline is broken.
  • The most achievable near-term reform is mandatory machine-readable form delivery to taxpayers — small change, large aggregate impact, zero political momentum.
July 2026 6 min read

The Industry That Runs on February Panic

Tax technology is the only sector I know that deliberately builds its entire business model around a single, government-mandated deadline — and then acts surprised every year when that deadline arrives. After fifteen years inside this machine, I have some thoughts.

The Calendar Is the Product

Every other software business I've studied tries to smooth demand. You add features, run promotions, find new markets — anything to flatten the revenue curve and stop the engineering team from burning out in Q1 and twiddling thumbs in Q3. Tax tech does the exact opposite. We sprint toward a cliff that is printed on every calendar in America, then we jump off it together, and then we spend the summer pretending that was fine.

April 15th isn't a deadline tax companies deal with. It's the product. The panic is the point. And once you see that, you can't unsee it.

What 'Seasonality' Actually Looks Like From the Inside

Here's what seasonality means in practice at a tax software company: in late January your monitoring dashboards start looking like a patient's heart rate when the nurse walks in. By mid-February you have executives checking server latency the way nervous pilots check altimeters. By the first week of April you are in a war room that someone has named something optimistic like 'Launch Central' and there are snacks — always snacks — as if granola bars are what stands between you and a five-nines outage.

Then April 16th arrives and it gets so quiet you can hear the HVAC. Half your contractors are gone. The Slack channels go dark. The same engineers who hadn't slept properly in six weeks are now being asked to think strategically about a roadmap for features that won't matter until January.

Tax tech is the only industry where your busiest day and your most dangerous day are the same day, and you knew it was coming twelve months in advance.

The Dirty Secret About 'Off-Season'

People outside the industry assume that off-season is when tax companies do their real engineering work. Build the platform, pay down the debt, modernize the stack. And yes, that's the plan on every roadmap deck I've ever seen. The reality is more complicated. The post-season hangover is real. Teams are depleted, sometimes literally smaller because contractors have rolled off. Leadership, flush with season revenue, immediately starts asking about next season's features — which means you're designing for the next cliff before you've finished falling off this one.

The technical debt that accumulates in a tax platform isn't just code shortcuts. It's architectural decisions made under time pressure that calcify because there's never a long enough quiet window to safely remove them. You end up with systems that work — and by 'work' I mean they process millions of returns without collapsing — but that look like a city that was never planned, just built in a hurry every February for thirty years.

Why Nobody Leaves

You'd think this would be a talent repellent. Brutal season, sleepy off-season, domain knowledge that doesn't transfer cleanly to fintech or e-commerce. And yet the retention I've seen in tax tech is genuinely surprising. I think it comes down to two things. First, the stakes are clarifying. When your software touches someone's refund — money they've been counting on, that might be the difference between catching up on rent or not — you feel that. The work has weight. Second, and I'll admit this is a little dark: engineers like problems with hard edges. April 15th is a hard edge. There's no negotiating with the IRS about the deadline. That kind of constraint, as exhausting as it is, produces a certain pride in the people who survive it repeatedly.

AI Is Going to Make This Weirder, Not Simpler

Everyone in tax tech is now layering AI into their products, and I'm one of the people doing it, so I can say this without judgment: the people promising that AI will 'simplify tax filing' are going to be partially right and mostly wrong. The AI will handle the obvious paths faster. But the US tax code is not a document that rewards confident summarization. It is a 75,000-page argument with itself. The edge cases — the ones that actually matter to real filers — are where the liability lives, and a model that is 94% accurate on tax questions has a bad error rate when those errors cost people money.

What AI is actually doing to the season model is interesting though. It's shifting the pressure. Less February panic about simple returns getting stuck. More year-round anxiety about whether the model has been updated for a regulatory change that dropped in November, or whether it's hallucinating a deduction that expired in 2019. The cliff is still there. We're just adding new ways to fall off it.

What I'd Actually Change

If I could redesign the industry's relationship with time, I wouldn't try to eliminate the season — that's the business, and it's not changing. I'd change how companies treat the six weeks after it ends. Mandatory slow-down period. No new feature commitments for thirty days. Structured retros on what actually broke, not just what almost broke. Time for engineers to write the postmortems they didn't have time to write during the fire.

The organizations that get good at tax tech over a long horizon are the ones that treat the off-season like a doctor treating recovery — actively, intentionally, with a plan — not like a coma you wait out until the next emergency. That sounds obvious. It is obvious. It's also not what most of us do.

The February Panic Is a Feature

After fifteen years, my honest take is this: the industry isn't broken. It's just organized around a very strange attractor. The panic, the cliff, the war room granola bars — they produce real software that real people depend on at one of the more stressful moments of their year. That matters. The question isn't how to eliminate the pressure but how to stop letting it be an excuse for the decisions we make — or don't make — the other forty-six weeks of the year.

I'll revisit this in April. I'll be in a war room somewhere, checking latency, surrounded by snacks. But I'll know exactly why I'm there.

Key Takeaways

  • Tax tech is uniquely organized around a single government-mandated deadline — and that shapes every engineering, hiring, and architectural decision in ways the industry rarely admits openly.
  • The 'off-season' is where the real competitive differentiation happens, but most companies waste it on planning for the next season before recovering from the last one.
  • AI won't eliminate the February cliff — it will move the anxiety from high-volume simple returns to low-volume edge cases with higher liability, which is arguably a worse problem.
  • The companies that win long-term in tax tech are the ones that treat post-season recovery as active and structured, not as a coma between emergencies.
July 2026 6 min read

Virginia Doesn't Care What You Think of It

I moved to Virginia thinking it was a placeholder — a sensible, boring address between bigger lives. Six years later I'm pretty sure I was wrong, and I'm not sure what to do with that. This is not a love letter. It's more of a grudging acknowledgment.

The State That Refuses to Have a Brand

Every state in America has a bit. Florida is unhinged. Texas is loud. California is expensive and convinced it's saving the world. New York is New York. These are lazy stereotypes, sure, but they're sticky because they have enough truth to function as shorthand. Virginia doesn't have a bit. Virginia is just... there. Present. Competent. Offering neither chaos nor spectacle. When I told people I was moving here from out of state, the most common response was a thoughtful pause followed by, 'Oh, cool.' That pause is doing a lot of work.

The Geography Is Quietly Insane

Here's what nobody puts in the brochure: Virginia is three states wearing a trench coat. You have Northern Virginia, which is effectively a DC suburb that happens to have a different governor, populated by defense contractors, federal employees, and data centers. Then you have the middle — Richmond and its orbit, which has actual culture, weird restaurants, and a chip on its shoulder about being overlooked. Then you have western and southwestern Virginia, which is mountains and small towns and an entirely different relationship with time. I live in a part of the state where I can be in DC traffic in forty minutes or standing next to a cow in twenty. This should not be possible. It is possible.

The Traffic Is a Character Study

I work in tax technology. I think about systems, bottlenecks, and failure modes for a living. Northern Virginia traffic is the most elegant demonstration of cascading system failure I have ever witnessed in the physical world. One fender-bender on I-66 propagates backward through the network with a precision that would make any distributed systems engineer both impressed and furious. I have sat unmoving on the Beltway for forty-five minutes because someone's bumper fell off six miles ahead. The locals have made their peace with it. They have podcasts queued. They have snacks. They have accepted that the road is not a road but a waiting room with lane markings.

'Virginia is the only place I've lived where you can have a genuinely good conversation about Civil War fortifications, data center power consumption, and crab pot regulations in the same week, with different people who each think their topic is the obvious one.'

The History Is Not Optional

I grew up in a place where history was something that happened somewhere else. Virginia does not offer you that comfort. You cannot drive twenty minutes in most directions without running into a battlefield, a marker, a cemetery, or a town that is in several history textbooks. My kids have absorbed more American history by proximity than I ever did in a classroom. The oldest can tell you about the significance of Fredericksburg with a matter-of-factness that I find both impressive and slightly unsettling. The state treats history like infrastructure — it's just part of the landscape, maintained and present, whether you engage with it or not.

The Weather Is Genuinely Adversarial

Virginia gets four seasons, which sounds like a feature. It is a bug. Summer is humid in a way that feels personal — the kind of humid where you step outside at 7am and immediately understand that the air has already won. Winter is inconsistent enough to be maddening: two inches of snow produces full societal shutdown, and then three weeks later it's sixty degrees and people are on patios. Spring is genuinely beautiful and lasts approximately eleven days. Fall is long and excellent and makes you feel like the weather is apologizing for everything else it did. I have a complicated relationship with fall here. I look forward to it with an intensity that would embarrass my former self.

It Made Me a Different Kind of Distracted

I build things for a living. I think about AI tooling, system design, and engineering team dynamics most of my waking hours. Virginia hasn't changed that. But it has added noise — good noise. There are trails near my house where I've solved more architecture problems than I have in any conference room. The state has this texture to it, topographically and culturally, that rewards going outside and being mildly uncomfortable. I don't know how to quantify the value of walking through fog on a November morning before a long engineering review, but I'd put it somewhere above 'useful' and below 'essential.' Which is basically how I'd describe Virginia itself.

The Grudging Part

I still don't tell people they should move here. That would be too much. Virginia doesn't need my advocacy and frankly wouldn't want it. But I've stopped treating it as a temporary address, a responsible choice, a sensible middle option. It's a real place with a real texture, and it suits me in ways I didn't plan for and can't fully explain. That might be the most Virginia thing about my relationship with Virginia: it works, I'm not entirely sure why, and I've decided to stop questioning it.

Key Takeaways

  • Virginia resists easy categorization — it's three distinct regions sharing a border and not much else, which is either a flaw or what makes it livable depending on your tolerance for ambiguity.
  • The Northern Virginia traffic system is the best real-world model of cascading distributed failure I've encountered outside a production incident.
  • History here isn't curated or optional — it's infrastructure, and it changes how your kids think whether you intend it to or not.
  • Living somewhere that refuses to perform for you turns out to be underrated. Virginia doesn't need to be exciting. It just needs to work.
July 2026 5 min read

What Two Years of Bedtimes Taught Me That Fifteen Years of Engineering Didn't

I spent fifteen years learning to make systems predictable — to remove variance, to write the test before the bug, to design so that the same input always produces the same output. Then I had a kid. A toddler is the most beautifully non-deterministic system I have ever tried to operate, and two years of bedtimes have quietly rewired how I think about control, patience, and what "done" actually means.

My entire career has been an exercise in making things predictable. You write the failing test first. You design the API so the same input always returns the same output. You add logging so that when something breaks at 2 A.M., the system can tell you exactly why. Fifteen years of that trains a certain kind of brain: cause, effect, control, repeat.

Then a small human arrives, and none of it applies.

A toddler is the most gloriously non-deterministic system I have ever tried to operate. The same input — same dinner, same bath, same three books in the same order — produces a peaceful sleep one night and a full-scale negotiation the next. There is no stack trace. There is no changelog. There is just a very small person who has, overnight, decided that socks are now unacceptable.

1. You cannot debug a feeling

My first instinct, the engineer's instinct, was to treat the meltdowns as bugs. Isolate the variable. What changed? Was it the nap, the snack, the weather? I'd run the whole diagnostic tree in my head while my daughter cried on the kitchen floor.

It took me embarrassingly long to realize the crying wasn't a defect to be fixed. It was just information — a two-year-old with a two-year-old's vocabulary trying to tell me something big with very small tools. The job was not to resolve the ticket. The job was to sit on the floor with her until the storm passed. Presence, it turns out, is not a patch. It's the whole feature.

2. "Done" is a lie I told myself at work

In software, "done" is a comforting fiction we all agree to. The story is closed, the PR is merged, we move on. Parenting has no merge. There is no state where the work is finished and you get to walk away from the repo. Every night resets. Every phase you finally understand is immediately replaced by a new one you don't.

Fifteen years of engineering taught me to remove variance from a system. Two years of fatherhood taught me that the variance was the point.

Strangely, this has made me better at my actual job. I've stopped treating "done" as the goal and started treating "still standing, still showing up" as the metric that matters. Teams are like that too. There's no version of leadership where you finish caring about your people and get to close the tab.

3. Patience is not a virtue, it's a runtime

I used to think of patience as a personality trait — something you either had or didn't. Fatherhood reframed it as a runtime environment. Patience is the amount of latency you're willing to tolerate between an action and the result you wanted, without throwing an exception.

A toddler will test that latency tolerance the way a load test hammers a server. Putting on shoes can take twenty minutes. Twenty minutes! For an operation that should take forty seconds. And the only two options are: raise your voice and poison the whole morning, or breathe, expand your timeout threshold, and let the small human do the small human thing. I am, slowly, learning to expand the timeout.

Here's the thing nobody told me: the skills that made me good at building systems actively worked against me as a father, at least at first. The impulse to optimize, to control, to reduce everything to inputs and outputs — that impulse is a liability when the system you're caring for is a person who mostly needs you to slow down and be there.

Two years in, I've stopped trying to debug my kid. I sit on the floor. I expand the timeout. I show up again the next night knowing the work is never done, and that this is the good news, not the bad. It's the best uptime commitment I've ever made.

Key Takeaways

  • The engineer's instinct to make everything deterministic actively backfires when the "system" is a small human.
  • Not every hard moment is a bug to fix — sometimes presence is the entire solution.
  • "Done" is a useful fiction in software and a harmful one in parenting and leadership; showing up consistently is the real metric.
  • Patience is less a personality trait than a timeout threshold you can deliberately widen.
June 2026 6 min read

The US Tax Code is the World's Worst-Designed Programming Language

Software engineers love complaining about legacy spaghetti code. But if you want to see a codebase that is truly on the brink of collapse, look at the Internal Revenue Code. It has circular dependencies, expired functions that are never deleted, and a parser that takes twelve months to return a compiler error. Here is why the tax code is the ultimate legacy system.

We software engineers think we have it hard. We whine about microservices that should have been monoliths, complain about Javascript framework churn, and write thinkpieces about the technical debt in our 5-year-old React applications.

But if you want to see a codebase that is truly, catastrophically broken; a system that handles trillions of dollars of throughput while running on logic that violates every known principle of computer science; you need to look at the US Internal Revenue Code (Title 26).

The IRC is not just a set of laws. It is a massive, Turing-complete codebase written in natural language, compiled by accountants, and executed on the brains and spreadsheets of 150 million taxpayers.

And as a software system, it is an absolute disaster. Here is why.

1. The Logic Rules are Patched by Non-Technical PMs

In a healthy software project, the people defining the business logic collaborate with engineers to ensure feasibility.

In the tax industry, the logic is defined by 535 product managers (Congress) who have never written a line of code in their lives. Every December, they push a massive, 4,000-page pull request called an "omnibus bill" directly to the production branch with zero unit tests, zero regression planning, and an absolute disregard for edge cases. If you think your company's product requirements are vague, try coding a system based on rules that were literally drafted in a smoke-filled room at 3:00 AM to secure a senator's vote.

2. Circular Dependencies are Built into the Architecture

One of the first rules of software engineering is to avoid circular dependencies: Component A should not require Component B if Component B also requires Component A.

The tax code has circular dependencies baked into the core engine. Consider the interaction between state income tax deductions and federal tax liability. To calculate your federal taxable income, you deduct your state tax paid. But to calculate your state tax liability, you need your federal adjusted gross income (AGI).

In computer science, this is a deadlock. In the tax industry, we solve this by having accountants run iterative calculations until the numbers stop moving; a manual, human-compiled loop that exists purely because the architects did not know how to design a clean API schema.

taxc — Internal Revenue Compiler v10.40
$ taxc --compile --optimize -f form1040.xml
[INFO] Initializing IRC parser engine...
[INFO] Loaded 74,000 pages of logic guidelines.
[WARN] Sec. 163(h): Deprecated mortgage interest deduction contains obsolete logic gates.
[WARN] Sec. 199A: Qualified Business Income calculation pattern is highly unstable.
[ERR] Compilation failed: Circular dependency detected in state_federal_loop.o.
[ERR] Stack overflow. Please run manual iterative reconciliation or hire a CPA.

3. "Dead Code" is Never Deleted

When a feature is no longer needed in software, you deprecate it and eventually delete the code.

In the tax code, code is almost never deleted. Instead, Congress uses "phase-outs." If they want to eliminate a deduction, they do not remove the section. They add a clause saying the deduction is phased out by 2% for every $1,000 of income above a certain limit, subject to inflation adjustments, unless you are a qualifying farm owner in a disaster zone.

The tax code is a codebase where the logic rules are written by a committee of 535 non-technical product managers with zero unit tests.

This leaves millions of lines of "dead logic" active in the system, forcing compilers (both human and machine) to evaluate thousands of conditional branches that apply to almost nobody. It is the legislative equivalent of leaving a decade of commented-out code in your repository "just in case we need it later."

4. Twelve-Month Compiler Error Latency

If you write bad code, your compiler tells you in milliseconds. If you deploy a bad build, your monitoring alerts trigger in seconds.

If you compile your tax return incorrectly, the compiler (the IRS) takes up to twelve months to send you an error message. And it does not come with a stack trace or a line number. It comes as a paper letter (the CP2000 notice) written in legal prose that demands payment within 30 days or it will trigger a manual debugger (an audit).

So the next time you are staring at a messy codebase and cursing the developer who wrote it, take a deep breath. Look at your clean IDE, your instant compiler feedback, and your automated test suite.

It could be worse. You could be compiling the tax code.

Key Takeaways

  • The tax code behaves exactly like an unmaintainable legacy software system with decades of technical debt.
  • Phase-outs and sunset clauses act as messy conditional patches instead of clean logic deletions.
  • The lack of automated testing or compile-time linting results in high error rates and delayed compiler feedback.
  • Tax complexity exists because we use the tax code as a policy steering framework, making clean architecture politically impossible.
February 2026 8 min read

Why I Built a Code Intelligence Platform in 6 Days (And What MCP Servers Actually Solve)

Everyone's talking about AI coding tools. But here's the problem nobody mentions: LLMs don't understand your codebase. They understand code in general. When your company has 63 repositories, a proprietary DSL, and calculation chains that span 15 files — "code in general" isn't enough.

At Taxwell, our tax calculation engine lives across two very different codebases: PowerBASIC (Drake) and MathMaster DSL (TaxAct). When we started using Claude Code for development work, we hit a wall immediately. The AI would confidently generate code using syntax that didn't exist. It would trace a calculation chain halfway and then fabricate the rest. It would suggest changes to functions without understanding that 47 other functions depended on them.

The answer wasn't better prompts. The answer was giving the AI a structured knowledge layer it could query. That's what Model Context Protocol (MCP) servers do — they give LLMs tools to look things up instead of guessing.

I built our code intelligence MCP server over a long weekend that turned into 6 days. The architecture is straightforward: an offline indexer parses all 63 repos and builds a SQLite database with FTS5 full-text search. Function definitions, call relationships, DSL field dependencies, cross-form references, include chains — all pre-computed and queryable. The MCP server exposes 37+ tools that Claude Code can call: search_code, get_call_chain, get_calculation_flow, get_form_dependencies, find_references.

The result? Questions that used to take hours of manual file-hopping now take seconds. "What breaks if I change this function?" has a real answer. "Trace the Earned Income Credit calculation end to end" returns the complete chain instead of a hallucinated approximation.

The lesson for other technical leaders

If your team is using AI coding tools and getting mediocre results, the problem probably isn't the AI. The problem is that the AI doesn't have access to the relationships and context that live in your engineers' heads. An MCP server — even a simple one backed by SQLite — can be the difference between an AI that wastes time and an AI that multiplies your team's output.

You don't need a vector database. You don't need embeddings. You need a well-indexed relational model of your codebase and a way for the AI to query it. Start there.

January 2026 6 min read

What Nobody Tells You About Merging Two Engineering Teams

When Cinven acquired TaxAct and Drake Tax, someone had to figure out how to make two very different tax development teams work as one. Here's what I learned about the human side of M&A integration that no playbook covers.

The tech was the easy part. Different codebases? Fine — we can build abstraction layers. Different deployment processes? Fine — we can standardize. Different testing philosophies? Fine — we can align on quality gates.

The hard part was that people had built their identities around their team. Drake developers were proud of being Drake developers. TaxAct developers had their own culture, their own inside jokes, their own way of doing things. Telling both groups "you're one team now" is about as effective as telling two families "you're one family now" at a forced reunion.

What actually worked

Shared problems, not shared mandates. Instead of reorganizing and hoping for the best, I gave both teams a shared problem to solve together. HappyFox ticket triage was the first one — everyone could see the customer pain, and fixing it required knowledge from both sides. Nothing bonds a team faster than a shared enemy, and "customer suffering" is a pretty compelling enemy.

Transparent career architecture. One of the first things I did was build a unified career ladder — Analyst I through Principal — with written job descriptions for every level. When people can see where they're going and what it takes to get there, a lot of the political anxiety disappears.

Let people grieve the old team. This sounds dramatic, but it's real. People had built careers on Team A or Team B. Acknowledging that something was being lost — not just something being gained — made the whole transition smoother.

Two years in, the team operates as a genuine unit. But it didn't happen because of a reorg slide deck. It happened because we focused on the work, built trust through shared wins, and treated the humans like humans.

November 2025 5 min read

From 38% SLA Breach Rate to 5.6%: A Dashboard Is Not a Dashboard

We had zero visibility into our support operations. No one could tell you how many tickets were open, who was handling them, or whether we were meeting our SLAs. Six dashboards later, our breach rate dropped by 85%. Here's the framework.

When I took over federal tax development, I asked a simple question: "How are we doing on support ticket response times?" The answer was a combination of shrugs and someone pulling up an Excel file from three weeks ago. That was the moment I knew dashboards weren't optional — they were the foundation.

But here's the thing about dashboards that most people get wrong: a dashboard that nobody looks at is worse than no dashboard at all, because it gives you the illusion of visibility. I've seen teams build beautiful Power BI reports that get opened twice and then forgotten.

The framework that worked

Start with one question, not one dataset. Our first dashboard answered exactly one question: "Which tickets are about to breach SLA?" Not a comprehensive ticket overview. Not a historical analysis. Just: what's on fire right now? That dashboard got used every single morning because it was immediately actionable.

Automate the delivery, not just the data. This is where Power Automate changed the game. I built a flow that sends an AI-generated daily recap to our Teams channel every morning before anyone starts work. Nobody has to remember to check the dashboard. The insights come to you.

Make it embarrassingly specific. Our dashboard shows which individual analyst handled which tickets and how long each one took. That felt uncomfortable at first. But when the top 5 analysts were handling 69% of tickets, that specificity led to redistribution that made the entire team healthier.

The 38% to 5.6% SLA improvement didn't come from working harder. It came from knowing where to look. That's what dashboards actually do when they're built right.