Posts

Pydantic: Catch Bad Data Before It Reaches Your Database

A library lets members borrow books through a web form. One day, a member types -5 into the loan period field, another mistypes her email, and a third pastes an ISBN with a letter in it. The form saves all three loans without complaint. The reminder email bounces, the -5 loan shows as overdue, and nobody can find the book with the broken ISBN. The database stored what it was given. The problem is that nobody checked what was given first. That is the gap Pydantic fills. You describe the shape of the data once, as a Python class, and Pydantic checks every record against it before your code trusts it. What I would check before using it My judgement is that Pydantic is worth adding the moment your code receives data it did not create: a form submission, a JSON body from an API, a row read from a spreadsheet. Inside your own code, a model is extra ceremony. At a boundary, where the data comes from a stranger, it is the cheapest insurance you can buy. The first check I would make is whic...

TanStack Query: Server State That Stays Fresh Without the Boilerplate

Two visitors open the same bookshop page a minute apart. The first one buys the last copy of a title. The second visitor's page still says one copy is in stock, because the data was fetched once at load and never checked again. She clicks buy, and the order fails at checkout. That gap is the problem TanStack Query is built for. Data from a server is not like the state inside your app. It lives somewhere else, it changes without telling you, it can fail to arrive, and a copy fetched five minutes ago may be wrong. TanStack Query keeps a cache of that server data, refetches it when it goes stale, and retries when a request fails. What I would check before using it My judgement is that TanStack Query earns its place the moment two parts of an app need the same server data, or one screen needs that data to stay fresh. A single fetch on a page that never changes does not need it; a plain fetch inside useEffect does that job with less to learn. The value shows up when the same book li...

Biome: One Tool to Lint and Format Your JavaScript

A small shop's checkout script starts as twenty lines in one file, then three developers edit it. One prefers single quotes, another double quotes. One writes two-space indents, another tabs, and a third leaves a half-finished discount variable behind after a refactor. Nothing is broken: the script runs and the totals are right. But every pull request now carries an argument about style, and real problems, like that unused variable, hide in the noise. Two tools usually police this: a linter for mistakes and a formatter for style, each with its own config. Biome folds both jobs into one binary, and this post puts that claim to the test on a real file. What I would check before using it My judgement is that Biome is worth trying once more than one person touches the JavaScript, because that is when style arguments start costing review time. First, I would check whether one tool can cover the rules you rely on. Biome ships with a linter and a formatter in one package, so there is ...

Drizzle ORM: Your Database Schema, Written in TypeScript

A small ceramics shop renamed one column. The orders table had a column called customer, and someone renamed it to customer_id. The shop's code built its queries by joining strings together, so nothing complained. The first sign of trouble came from a customer, whose order page showed a blank where her name should have been. The query had failed quietly, and nobody noticed until she did. That is the problem an ORM is supposed to solve: the database and the code should agree about the shape of the data, and a rename should break loudly at build time instead of quietly in production. Drizzle ORM takes an angle on that promise, and this post tests whether it holds up. What I would check before using it My judgement, from years of building small web apps, is that Drizzle is the right call when you like SQL and want the compiler to watch your back, and the wrong call when you want the database to disappear entirely. Drizzle does not hide SQL the way some ORMs do. You write queries tha...

Zod: Stop Bad Data at the Door of Your Checkout

A customer fills in a checkout form and picks two ceramic mugs and a linen tote. Somewhere between the form and the server, the quantity turns into the string "2" instead of the number 2. TypeScript does not catch it, because TypeScript checks code before it runs, not data arriving while the program is live. The server adds the quantity to the total and the maths produces nonsense, or the order saves with a quantity nobody can fulfil. The bug is not in the form or in the maths. It is in the gap between what the code expects and what actually arrives. Zod closes that gap: describe the shape of the data once, and check every order against it. What I would check before using it My judgement is that Zod is worth adding the moment your code receives data it did not create: a checkout form, a webhook from a payment provider, a response from another team's API. At a boundary, types are only a promise, and Zod is the check that the promise holds. The first thing I would check i...

Hono: One Small API That Runs Almost Anywhere

A small bookshop wants an API. Customers should be able to list the books and place an order, and the shop owner wants it live this week on a cheap host. Next month she might move it to a Node server or a serverless host that charges per request. Most frameworks are tied to one runtime, so the usual answer is to write the API once and rewrite it when the host changes. The routes and validation stay the same; only the plumbing changes. Hono exists for exactly this situation. It is a tiny web framework that runs the same code on Node, Cloudflare Workers, Deno, and Bun, so the API stays put when the host changes. What I would check before using it My judgement: reach for Hono when the API is small and you are not sure where it will run. A bookshop API, a webhook receiver, or a small service in front of a database are the honest cases. The code stays short, and moving from Node to a serverless host means changing the adapter, not the routes. If the API will live on one Node server foreve...

WebSockets Explained: Real-Time Data Without Polling

A customer adds a ceramic mug to their basket on a small shop's website, then waits. The order page says Processing, and nothing changes until they refresh. The server knew the order shipped ten minutes ago, but the page had no way of hearing about it. The usual fix is polling: the page asks the server "anything new?" every few seconds. Most of those requests get the answer "no", yet each one opens and closes a connection for nothing. WebSockets exist for exactly this gap. One connection stays open, the server pushes a message the moment something changes, and the page updates without asking again. The question is whether your page needs a live wire at all. A WebSocket starts as an ordinary HTTP request that asks the server to upgrade the connection. If the server agrees, that same connection stays open for two-way messages, and either side can send at any time. That is the whole idea. The rest of this post is about deciding when that open connection earns its ...