Skip to main content
technical writing

Notes on the craft of shipping software.

Practical articles about frontend architecture, systems programming in Rust, release engineering, developer tooling, and the everyday decisions that shape software quality over time.

Featured | March 2026 | 12 min read

Zero-downtime migrations: moving a live database without losing sleep

Database migrations are the most anxiety-inducing part of any deployment. A schema change on a table with fifty million rows can lock your application for minutes if you are not careful. This article walks through the expand-and-contract pattern, online schema change tools, dual-write strategies, and the testing approach I use to validate migrations against production-scale data before they touch the real database.

The key insight is that every migration should be reversible without data loss. If your rollback plan is "restore from backup," you do not have a rollback plan. You have a prayer. This post provides concrete techniques for PostgreSQL, practical tooling recommendations, and a checklist you can use on your next release.

PostgreSQL DevOps Architecture
Read full article
migrate_users_table.sql
-- Step 1: Add new column (non-blocking) ALTER TABLE users ADD COLUMN email_verified boolean DEFAULT false; -- Step 2: Backfill in batches UPDATE users SET email_verified = true WHERE id BETWEEN 1 AND 10000 AND verified_at IS NOT NULL; -- Step 3: Add constraint after backfill ALTER TABLE users ADD CONSTRAINT chk_email CHECK (email_verified IS NOT NULL) NOT VALID; -- Step 4: Validate (non-blocking) ALTER TABLE users VALIDATE CONSTRAINT chk_email;
February 2026 9 min read

Designing dashboards engineers will actually use

Most internal dashboards fail because they display data without context. Engineers open them, scan for red, then close them without taking action. The problem is not the data. The problem is that the dashboard requires the viewer to do mental translation before they can act. This post breaks down a framework for dashboard design that surfaces the next useful step instead of just the current state.

dashboard-config.ts
interface DashboardPanel { metric: string; threshold: { warn: number; critical: number }; action: string; // What to do when threshold breached owner: string; // Who is responsible }
React Architecture DevOps
Read article