Five years maintaining Kong Insomnia
I merged my first PR into Kong Insomnia on 31 August 2021 — a small fix to how the tag editor cast values to booleans. I didn't know at the time it'd turn into five years and 665 merged PRs in that one repo alone, or that I'd end up the project's second-most prolific contributor of all time, behind only the person who originally built it. Counting the rest of the public Kong org — the client's mock server, the native networking binding, shared UI components, internal tooling — the real total is 750 merged PRs, and that still doesn't include the private repos I also worked in, which aren't publicly countable at all. That run has come to an end: the decision wasn't mine, the team is moving on to a different project, and I'm not going to get into the specifics of why here. What I want instead is the same thing I try to do with everything on this site — look at what happened, honestly, rather than oversell it or pretend it didn't matter.
What five years looks like in PRs
The shape of the work changes a lot when you look at it year by year rather than as one lump sum:
- 2021 (from September) — 27 PRs, finding my feet
- 2022 — 163 PRs
- 2023 — 159 PRs
- 2024 — 158 PRs
- 2025 — 87 PRs
- 2026 (through August) — 71 PRs, ending on the largest single piece of work of the whole five years
Three straight years of 150+ merged PRs is the part I'm proud of — not any single feature, but that pace held up across years, across a shifting team, across however many different priorities Kong had at any given time. Open source maintenance has a reputation for burning people out in bursts; what I found more true in practice was that the unglamorous, sustained throughput mattered more than any individual PR.
Worth saying plainly what all that volume was in service of: over the same stretch, Insomnia grew into a genuinely strong enterprise business, with 135,000 weekly active users at the point I'm writing this. None of the individual PRs above are impressive in isolation — a protobuf refactor, a migration off Lerna, a one-line OAuth2 debugging fix — but that's what it looks like to build and maintain software at a scale where 135k people depend on it working correctly every week. The unglamorous throughput and the business outcome aren't two separate stories. They're the same one.
And to be clear about scale: my 665 PRs to that one repo sit inside roughly 3,158 merged PRs from everyone over the same window — the rest of the core team, plus a wider open-source community contributing on top of it. I was a large contributor, not the whole effort, and a five-year retrospective from just one person's PR count would badly undersell how many people it actually took to get Insomnia to 135k weekly active users.
What actually got built
Insomnia is an API client — REST, GraphQL, gRPC, WebSockets, MQTT — plus an OpenAPI-to-Kong config designer bolted on for Kong's own use case. Across five years I touched most of it, but a few threads run through the work that I'd point to as the real substance:
-
Protocol support that got exercised for real.
GraphQL support went through multiple hardening passes (I have
PRs literally titled "GQL second pass," "GQL third pass" —
nothing about protocol support is ever really "done," you just
stop finding the next bug). WebSocket support gained custom CA
certs for mTLS. gRPC tooling got a protobuf refactor that let
us drop a forked copy of
protobuf.jswe'd been carrying — a small PR by diff size, a real reduction in maintenance surface by consequence. - OAuth2, repeatedly. Optional redirect URIs, implicit-flow response type defaults, general correctness fixes — OAuth2 is one of those specs where "compliant" and "works with what real identity providers actually send" are two different bars, and most of my OAuth2 work over the years was closing that gap one provider's quirk at a time.
- Reliability work nobody notices until it's gone. One PR I still think about: a single fix that resolved roughly 248,000 Sentry error events. Not a feature, not something anyone requested by name — just database migration logic that was quietly failing for a meaningful slice of users on every launch.
- Disabling Node integration in the main renderer window. This is the single most consequential security change of the five years. Electron apps default to a genuinely dangerous posture: the window rendering your content — including content you didn't write, like an imported collection or a response body — has full Node.js access unless you explicitly turn it off. Turning it off is table stakes for Electron security and also a real amount of work, since anything that quietly relied on that ambient access needs a proper IPC bridge instead. Everything else in this security list — the sandbox, moving libcurl out of the renderer — is really downstream of getting this one foundational thing right first.
- Getting libcurl out of the renderer. It used to run inside the same process that renders untrusted, user-controlled content — exactly the process you don't want your native networking layer sitting in. Invisible to a user, foundational to everything downstream of it: you can't reason cleanly about what a script can touch if the networking layer itself is in the wrong process to begin with.
- Auth, torn out and rebuilt. Insomnia used to lean on SRP (Secure Remote Password) for account auth — we removed it, and shipped passwordless login in its place. Simpler mental model for users, smaller attack surface for us, and one less protocol implementation to keep correct.
-
The last major project: a from-scratch security
sandbox. Pre-request and after-response scripts used
to run inside a hidden Electron
BrowserWindow— full Node.js access, no isolation, for scripts that could come from a shared/imported collection you didn't write yourself. The project I was in the middle of when the team moved on was migrating that execution model to a QuickJS-WASM sandbox: capability-scoped bridges instead of ambient Node access, vetted npm libraries exposed deliberately rather than viarequire(), an explicit trust model (pluginSandboxEnabled) replacing an implicit one. It shipped as opt-in, with 195 unit tests and an end-to-end smoke test that specifically exercised a runaway script getting isolated instead of freezing the whole app. It's the piece of work from this whole run I'd point to first if someone asked what "good" looks like in this kind of job — not because it was clever, but because it closed a real, un-flashy security gap that had been sitting there the whole time, for users who had no way of knowing it existed.
Rebuilding the stack while it kept shipping
The security work is the part I'd lead with, but it wasn't the biggest volume of change. Underneath the features, almost every major piece of the app's foundations got replaced at least once across five years — usually incrementally, always without stopping feature work to do it:
- Redux — removed, incrementally, over a long stretch rather than a rewrite sprint. The kind of migration that only works if you resist the urge to do it in one heroic PR.
- Class components converted to function components across the codebase; MUI replaced with React Aria; styled-components removed; Bootstrap removed. Four separate "how we write UI" decisions, each one fully unwound and replaced.
-
The internal
send-requestworkspace abstraction removed once it had outlived what it was built for. -
Lerna replaced with native npm workspaces;
ts-jestreplaced with Vitest; Nunjucks replaced with LiquidJS for request templating — all the kind of infra swap that pays for itself in CI time and contributor sanity, but never shows up in a user-facing changelog. - Playwright adopted for end-to-end testing, plus a dedicated pre-release test pass before every version went out — directly responsible for the QuickJS sandbox work above shipping with real E2E coverage rather than just unit tests.
- Automated GitHub App-based releases, replacing whatever manual process came before.
- The website rebuilt from Gatsby to a backend-for-frontend architecture on React Router, and the hosting moved off Vercel onto a GCP Cloud Function — a framework migration and an infrastructure migration done together rather than as two separate projects six months apart.
- Consistently ahead of the curve adopting new Electron versions — Electron apps have a well-earned reputation for lagging a major version or three behind; Insomnia mostly didn't.
None of this was one person's work, and volume like 665 PRs isn't something you sustain alone — it's something two or three people make possible for you by being consistently, reliably there on the other side of a review. Looking back at who was actually approving my PRs over the years, it's overwhelmingly filfreire and gatzjames — not close. A fast, thoughtful reviewer is a force multiplier in a way that's easy to undervalue until you don't have one: it's the difference between a PR sitting for three days losing momentum and a PR landing same-day so you can build the next thing on top of it while the context is still fresh in your head. Whatever pace I kept up across five years, a real share of it belongs to the two of them for keeping the review loop tight enough that the energy and inertia never had a chance to drop.
What the job actually teaches you
A few things stuck with me that I don't think you learn any other way than doing this for years, not months:
Volume is a skill, not a grind. 665 PRs isn't 665 individually memorable moments — it's mostly small, correct, well-scoped changes that compound. The skill isn't heroics on any single PR, it's keeping the unglamorous parts (migrations, error handling, upgrade churn) moving at the same steady rate as the visible parts, because users don't experience your codebase as a changelog — they experience it as whether it broke today.
The biggest wins are usually invisible by design. The 248k-error fix and the QuickJS sandbox have almost nothing in common on the surface, but they share the same shape: the value was in something going wrong less, not a feature getting announced. Nobody writes you a thank-you for an app that didn't crash or a script sandbox that quietly closed an attack surface. That's fine. It's still the actual job.
Security work is scoping work, mostly. The sandbox migration wasn't hard because WASM is exotic — it was hard because getting the trust boundary right (what's exposed to a script, what isn't, what "opt-in" actually protects against) takes more judgment than code. Most of the PRs in that project are named things like "capability & bridge-handler scoping audit" for a reason — the audit is the work.
The timezone math never worked out evenly
The part of this job that's hardest to capture in a list of PRs is that I did all of it from Europe, on a team spread across New Zealand, Vancouver, Shanghai, and India — which is about as close as you can get to covering the entire 24-hour clock with one team. There is no meeting time that's reasonable for all of those places at once. New Zealand is roughly half a day ahead of me; Vancouver is roughly half a day behind. Put those two in the same standup and one of them is losing regardless of what time you pick.
In practice that meant standups that landed at 10pm some days, or right at dinner time on others, layered on top of a normal 9-to-5. You don't get to swap one for the other — the daytime work still has to happen, so the late meeting is just added on top of the day rather than replacing part of it.
The part I didn't expect going in: despite that, we ended up with fewer total engineering meeting hours than most companies I've worked at with much easier, same-region overlap. When there's no comfortable shared window, you stop defaulting to a meeting for everything — you write it down, you leave it as a comment on the PR, you let async review do the job a meeting would have done somewhere with better overlap. The spread that made scheduling genuinely hard is the same thing that forced good async discipline on the team by necessity, not by choice. I don't think we'd have arrived at that discipline voluntarily if the timezones had been kinder to us.
Where that leaves things
"Five years" wasn't just a stretch of PRs, either — it was a real chunk of my life running in parallel with all of it. I proposed, got married, had my son, and bought my first house across this same period. I also started therapy, ran my first marathon, and learned to play piano. None of that is in the git log, but it's the actual backdrop everything above happened against, and I don't want to write a five-year retrospective that pretends otherwise.
How I actually feel about the move is more mixed than a tidy
narrative would suggest, and I'd rather say that plainly than
smooth it over. I'm genuinely relieved — ecstatic, honestly — to
be done with a specific handful of low-value-add corners of the
app: request mocking (26 PRs of my life went into
insomnia-mockbin alone), OpenAPI spec authoring,
private plugins, and especially the CLI, which was designed to
bundle the entire desktop app inside it and was brittle and
exhausting to keep working as a result. node-libcurl
deserves its own mention — 21 PRs and a thankless amount of time
spent keeping a native binding compatible with
every Electron bump, for years, with basically no one ever
noticing it was hard. I get to forget all of that completely
now, and I'm not going to pretend that doesn't feel good. I'm
proud of what got built, and of the pace and quality it got
built at. I'm also a bit sad it
never got the recognition from leadership that the scale of it
deserved — not looking to relitigate that here, just noting the
gap. I'm annoyed I don't get to finish the sandbox work myself;
it's the piece I'm proudest of, and I wanted to see it through
to being the default, not just opt-in. And I'm sad about not
getting to keep working with the team in Shanghai specifically
— that's a real loss, not a footnote.
What I do know is what five years actually produced: a client people use daily, a security model that's meaningfully better than the one I found, and a body of work I can point to concretely rather than describe vaguely. I'm not committing to what's next in this post — that's a separate piece, for when there's something real to say. For now, this is just an honest accounting of what the last five years were.
Thanks to everyone I worked alongside on this, on both sides of a PR review, over five years. It mattered.