I like the part of the system that only misbehaves under load.

I am a senior software engineer in Seattle. Most of what I write about lives in the unglamorous middle of an application: data models that survive contact with reality, query plans that quietly stop being true as a table grows, and background jobs that fail loudly instead of silently.

Nearly every essay here starts with a real production problem and a number attached to it. A page that counted 800 million rows. 319 N+1 queries across a fleet. A petabyte of media sitting on the wrong storage tier. A goroutine leak with no stack trace, no panic, and no failing test.

Taking on contract work: existing Rails and Postgres apps, data you need to trust, cloud bills, and first versions that have to hold up in production. Work with me · Also: outreach, press and podcast pitching
Featured in the pressGeekWire · October 1, 2026

Startup Spotlight: Porchlight uses AI to help foster human connection in senior care

“Donahue is the founder and sole builder of Porchlight, a newly launched life-story and reminiscence tool designed for assisted living and memory care communities.”

I’m Patrick Donahue. I designed, built and run Porchlight on my own, from the one-button resident recorder to the staff briefings and the family relay.

Contract work

Where I am most useful

Mostly existing Ruby on Rails and Postgres applications with real users, real data and a bill that keeps growing. The tools are the normal modern ones. What you are paying for is knowing what to change, what to leave alone, and saying so plainly. How an engagement starts →

An app that got slow or stuck

Pages that were fine at ten thousand rows and are not at ten million, jobs that fail quietly, the framework upgrade that has been half finished for a year.

Data you need to be able to trust

Code can be rebuilt in a few weeks. Years of bad data cannot. Constraints, audit trails, reconciliations and migrations that keep the history honest as the model changes.

A mature app that costs too much to run

Once a product is stable, the work is making it cheaper: storage tiers, database sizing, hosting nobody has re-checked since launch.

A first version that now has customers

Built fast, often with AI tools, and it works well enough that people depend on it. The product decisions are already made. I put them on a foundation that holds up: a real data model, tests, and deploys you can repeat.

What I am deep in right now

Static analysis for bugs that leave no evidence

Goroutine leaks are a genuinely nasty class of bug: no stack trace, no panic, no failing test, just a process that slowly gets worse until someone restarts it. I have been building tools for that, and benchmarking them somewhere honest.

tether

Static goroutine-leak analyzer · Go, x/tools/go/analysis, go/cfg

Treats every go statement as a proof obligation: either find a termination witness, or report it with a concrete escape path. I pointed it at the entire Go 1.25 standard library, which is the only honest way to find out whether a tool like this is real.

  • 91 → 21diagnostics after seven fixed false-positive classes, with no true positives lost
  • 0findings in non-test stdlib code
  • 1real WaitGroup hang found in the database/sql tests

weave

Deterministic interleaving explorer · Go, zero dependencies

The Loom-shaped gap in Go. Runs one goroutine at a time through a stateless DFS with replay, so a concurrency bug that shows up once every ten thousand runs becomes something you can reproduce on purpose and then shrink to its smallest failing schedule.

  • vector clocksrace detection across explored schedules
  • delta debuggingminimises a failing interleaving automatically
  • CHESSpreemption bounding to keep the search finite
Recurring obsessions

The four things I keep coming back to

Written over several years and a lot of production incidents. Grouped by the problem rather than the technology, because the technology keeps changing and the problem does not.

Postgres that stops being the problem

The most common reason a growing app feels bad is a query that was fine at ten thousand rows and is not fine at ten million, and nobody noticed the week it changed.

Reading the bill instead of accepting it

Cloud spend is treated like weather. It is usually a lifecycle rule written years ago against an access pattern nobody re-verified.

Engineering services

You know the business. I'll make the software hold up.

From a first version built with AI tools to a ten-year-old Rails app: the engineering underneath, left documented so any developer after me can pick it up. Every engagement →

Talk to me about this

Tell me what you're working on

One or two sentences is plenty. What do you have, what is going wrong, and what would good look like?

One reply from me within a business day. No newsletter, no sales sequence, no calls you did not ask for.
Got it, thank you. I read every one of these myself and will reply within a business day with a couple of questions and a time to talk if it makes sense.
For businesses without an engineer

The busywork I take off your plate

Eleven plain-language pages on the specific things I set up for businesses without a technical person: the phone that gets answered, the invoice that gets chased, the report that builds itself. Each one walks through a business shaped like yours and ends with a form, not a price list. For the long version, The AI Pioneer holds fifty-four plain-language guides.

How I work

The Unattended Playbook

Six essays on running cold outreach, a demo-per-prospect pipeline and a fleet of browser tabs with coding agents, unattended, on one laptop. Every method is described in full. The scripts and the rules file are what I install on your machine.

Recent

Latest writing

All 65 essays →

A little context: I studied history, which nobody hires an engineer for, and which turned out to be four years of practice at the thing this job actually is. You get handed incomplete, contradictory sources and have to produce a defensible account of what happened, while being explicit about which parts you are confident in and which parts you are inferring. That is a debugging session. It is also what reading an unfamiliar codebase feels like.

I have spent the last several years as the senior engineer on a small team, which is a particular kind of education: there is nobody to escalate to. If the database is slow at 2am, that is yours, and you also get to be the one who explains it afterward.

Off the clock I build a lot of small strange things, mostly because the cost of building a small strange thing collapsed, and I host them myself because owning the deploy path teaches you things that reading about it does not. The longer introduction →