The best bug reports were written by the suspect
In a project I worked on — the order back office for a group of e-commerce shops — a rule engine decides which orders ship automatically. Invoice payment is…
51 posts
In a project I worked on — the order back office for a group of e-commerce shops — a rule engine decides which orders ship automatically. Invoice payment is…
I clicked the logo on one of my sites and the homepage opened inside a modal. Dimmed backdrop, rounded corners, the full page — header, hero, everything — re…
Java's garbage collector hid lifetimes. Ruby hid types. Rails hid HTTP. Hibernate hid SQL. EC2 hid hardware. For three decades, programming languages and fra…
Every team I've worked with that ships a tabular ML model has, at some point in the last two years, been asked the same question by someone in leadership: "H…
This site's runtime Docker image was 423 MB. A large share of that was Prisma CLI tooling the server never imported — migration engines, Studio, a PGlite dev…
This site runs on TanStack Start with Bun, backed by a Railway-managed Postgres. Railway's autobuild (Nixpacks) detects Bun projects just fine. What it doesn…
This site runs on TanStack Start with Prisma 7 against PostgreSQL, on the Bun runtime. The three of them fit together cleanly, but there are a handful of sma…
We had a wide MySQL table — think analytics events: one row per visit, lots of text columns for URLs, referrers, UTM parameters, click identifiers. Around 8…
FastMCP is the lightweight Python framework for building MCP servers — the kind of server that exposes tools to an AI agent. OpenAI's Responses API can call…
You want one URL — printed on a sticker, stamped into a QR code, pasted in an email — that takes a visitor to your app in the store appropriate to their devi…
Python's runtime handles memory for you, but every so often you'll see code that tries to give it a nudge. The two ways that come up are:
Node has shipped a built-in WebSocket client. It landed experimentally in Node 21 (October 2023), graduated to stable in Node 22 LTS, and in 2026 is just par…
TypeORM still ships with NestJS templates and still works fine, but the ergonomics have aged badly compared to Drizzle and Prisma. If you're stuck on TypeORM…
TanStack Router gives you two ways to style the active link in a navbar — activeProps for component-level prop merging, and a data-status="active" attribute…
For years, every Node project started the same way: npm install dotenv, require('dotenv').config() at the top of index.js. Node 20.6 (Sep 2023) finally shipp…
Default browser print stylesheets look broken on most websites — navs, footers, dark themes, and interactive elements all carry over to paper. Tailwind has a…
HTTP caching done well saves bandwidth, server load, and round-trip time at once. Done badly, it ships stale content or hits the origin on every request. The…
The "esbuild over tsc" pitch has narrowed since 2023 — Node 22 added --experimental-strip-types, Node 23+ runs TypeScript files directly with no flag, and Bu…
The package.json scripts block is the one configuration surface every Node project agrees on. It's also where most projects accumulate the most rot — half th…
In today's software-driven world the complexity of applications and their settings often overwhelms users. Every app seems to come with its own intricacies a…
The AWS CLI uses two files in /.aws/:
The full node:22 image is well over a gigabyte uncompressed and ships with the entire Debian userspace — bash, apt, perl, a dozen utilities your app will nev…
On smaller projects, dependencies drift out of date faster than you can keep up, and npm itself doesn't ship a bulk-upgrade command — npm outdated shows what…
A Node process inherits the user's full filesystem and process-spawn rights by default, which means any third-party dependency you install can read your /.ss…
Force-pushing is fine on personal branches and topic branches with no other contributors; it's a footgun anywhere else. The safer command is git push --force…
patch-package lets you keep a local diff against an installed dependency and replay it on every install — useful when an upstream bug blocks you and you can'…
Object destructuring of function parameters is the right default for any function with three or more parameters, any optional ones, or a signature you expect…
In 2023 I argued native mobile apps were missing HttpOnly cookie support and that web apps had a security advantage as a result. Three years on, the framing…
When you ship icons in a React Native app, it's tempting to export a separate file for every stroke width and color. You don't have to. SVG's presentation at…
Layout on the web has cycled through five or six paradigms in thirty years. Each one looked permanent at the time. Here's the trail, with the code each era l…
MongoDB has no native rename-database command. The move is mongodump followed by mongorestore into the new name — the old database stays in place until you d…
A handful of PostgreSQL one-liners I keep going back to.
Axios is the Node HTTP client most people reach for by default, but got and Node's built-in fetch (Node 18+, backed by undici) are both worth a look first.
A 5-minute trip through HTTP, version by version: what each one added, what stuck, and what quietly didn't.
Ctrl+Z sends SIGTSTP and stops the foreground job — it's frozen, not running, consuming no CPU until resumed. Ctrl+C (SIGINT) terminates it instead.
The macOS hostname is split across three scutil keys, and the one that drives your shell prompt isn't the only one you usually want to set:
If you already have Homebrew, you don't need nvm to juggle Node versions on macOS. brew unlink / brew link handles it.
Originally published April 2023, in a series with Parts 1 and 2 of the perf gotchas posts. Modern V8 / Maglev / Turbofan have made the original framing a bit…
Originally published April 2023, follow-up to Part 1. Modern V8 / SpiderMonkey / JavaScriptCore have made parts of this advice obsolete — the entries below a…
Originally published April 2023. Modern V8 / SpiderMonkey / JavaScriptCore have made most of this advice less load-bearing than it was — the entries below ar…
Originally written for Expo Router v1 in April 2023. The API has since moved — what's below is the current pattern as of Expo Router v3+ (Expo SDK 50+), stil…
The error error: src refspec production matches more than one appears on git push production when the unqualified ref resolves to both refs/heads/production…
Sorting and range queries against date fields silently break when the values are stored as strings. Convert them in place — the pipeline form of updateMany (…
Historical note: this is an Xcode 14 / React Native <0.70.3 issue. Modern Xcode 16/17 plus RN 0.74+ (New Architecture default in 0.76) handle this upstream —…
When working with initial migrations in a project it is often helpful to drop all tables and then re-run all migrations. Instead of removing and re-creating…
Default VS Code text rendering on macOS Retina can look fuzzy because the editor doesn't pick up the system's font smoothing. One setting fixes it.
Archive, upload, get rejected because the build number didn't change. Automate the bump and stop hand-editing it before every TestFlight push.
Running Grafana k6 at meaningful load from a fresh EC2 box hits two snags before any test runs: the kernel and shell defaults aren't tuned for tens of thousa…
When VS Code launches a Node program for debugging, it doesn't pick up the variables from your project's .env file. The instinct is to wedge -r dotenv/config…