The Daily
A note a day on APIs and the realities of shipping web applications. Stuff I've actually learned across 25 years of doing the work.
The GitHub Actions Concurrency Key Everyone Skips
Every push to a branch queues another workflow run. Most of them are pointless. One setting fixes it and almost nobody uses it.
I was burning through free GitHub Actions minutes faster than made any sense. A client's monorepo - Laravel API, a React front end, a few worker processes - had five or six workflows. I'd push a branch, realize I forgot a , push again thirty seconds later, and both runs would chew through the full pipeline in…
Read the daily →S3 Event Notifications vs. Polling: What Actually Makes Sense at Small Scale
Everyone defaults to S3 Event Notifications for file pipelines. After running both in production, I think polling is underrated - and cheaper than you'd expect.
S3 Event Notifications feel like the obvious answer the moment someone says "we need to process files when they land in S3." Serverless, event-driven, near-real-time - it hits all the right notes. But I've built enough of these pipelines to know the obvious answer isn't always the right one, especially when your…
Read the daily →The Real Math on RDS vs. a Tuned MariaDB VM
Everyone says 'just use RDS.' I run managed hosting and I've done the math. Here's what it actually costs you.
RDS is the right answer for a lot of teams. It's not the right answer for mine, and I suspect it's not the right answer for a lot of small hosting shops either. Here's the math I did, and why I keep landing on a well-tuned MariaDB VM for most of my managed clients. The Setup NWOS runs managed hosting for somewhere…
Read the daily →Docker Compose volumes: the silent data-loss trap I keep seeing
Anonymous volumes in Docker Compose look identical to named volumes until you run docker-compose down and your data vanishes. Here's what to watch for.
I've watched junior devs - and honestly a few senior ones - lose days of local database state because of a single missing string in a . Not a typo. Not a wrong password. A volume declaration that looks correct but behaves completely differently under . This one is subtle enough that I want to write it down. What the…
Read the daily →Vite HMR Through nginx in Docker: the WebSocket Config Nobody Documents
Getting Vite's hot module replacement to work through an nginx reverse proxy in Docker took me longer than it should have. Here's the exact config.
Every time I set up a new Dockerized dev environment with Vite behind nginx, I waste at least two hours on the same WebSocket problem. The HMR connection silently fails, the browser console shows a cryptic WebSocket error, and nothing in the Vite docs or the nginx docs quite covers the intersection. I'm writing this…
Read the daily →