Correctness

The Words You Inherit

Every system hands you a vocabulary before it hands you a problem. The names you didn't choose draw the boundaries you can see, and a wrong one doesn't confuse you — it quietly removes designs from consideration.

Words Are Infrastructure

Naming gets treated as a documentation concern — a matter of clarity and taste. It behaves like a schema decision: cheap for an afternoon, load-bearing forever, and reviewed like neither.

Code Doesn't Keep

Code that never runs isn't preserved — it holds references to an environment that keeps moving without it. The common path is continuously re-validated by reality; the rare path is a stopped clock nobody has looked at.

The Rare Path Gets Rarer

Every fix to the common path makes the exception path less frequent, less familiar, and less examined — so reliability work quietly concentrates your remaining risk in the code nobody has watched run.

You Can't Store Readiness

Execution is the only maintenance mechanism that reliably works, and nobody schedules it. That makes readiness a flow rather than a stock — which is why the only honest question about any part of a system is when it last actually ran.

Can't Reproduce Is a Measurement

Failing to reproduce a bug tells you something real. It just doesn't tell you the thing most people close the ticket believing it said.

The Only Failure That Counts

Both halves of reproduction — succeeding and failing — quietly replace the reporter's failure with yours. Only one of the two is the bug.

The Repro Is a Model

Getting a bug to reproduce feels like the end of the investigation. It's the point where you quietly substitute your version of the failure for theirs.

The Decision Nobody Made

Most of a system's shape was never chosen. It's the fossilized remains of whatever was expedient the first time, and it constrains everything downstream as firmly as if someone had decided it on purpose.

The Question That Doesn't Decay

Provenance is a proxy. What actually holds a system's shape in place isn't anyone's reasoning — it's the count of things standing on it, and that you can measure at any time.

One Choice, Two Costs

Picking a metric and starving the work it can't see aren't two separate problems. They're the same act, viewed from either side.

The Metric Stopped Being the Thing

A proxy measurement is only honest for as long as nobody is optimizing against it yet. The moment it becomes the target, it starts drifting away from the thing it was supposed to represent.

The Work That Never Shows Up

Every measurement system creates two categories: work that counts and work that doesn't. The second category is where prevention lives, and it starves quietly.

Assume It's Load-Bearing

You inherited code with no explanation attached. The safe default is not caution, and it is not confidence — it is finding out.

The Button That Means Four Things

Delete is the one word in a product that every user thinks they understand and every implementation defines differently.

The Copies You Forgot About

Deleting a record is easy. Deleting every derivative of that record is the part nobody scoped.

Undo Is Not a Feature You Add Later

Everyone agrees users should be able to take it back. The disagreement is about how much the system has to remember, and for how long.

They Type What They Remember

Search inside a product fails on the queries people actually make: partial names, misspellings, and the one detail they happen to recall.

Let Them Take It With Them

Export is the feature nobody demos and everybody evaluates. A product that makes leaving hard is not one people commit to.

Somebody Has to Decide What Matches

Import and export are one-time events. Keeping two systems agreeing is a permanent one — and the hard part is identity, not transfer.

The Import Is the First Impression

The first thing a new customer does with your product is hand it a file of their real data. Whatever happens next is what they learn about the software.

Every Notification Spends Attention

Notifications get added one feature at a time, each individually justified. Nobody owns the total, and the total is what determines whether any of them get read.

Let Them Turn It Off

Notification preferences look like a courtesy. They're actually the mechanism that keeps the channel usable — and the coarser they are, the more people mute everything.

The Message That Arrived Twice

Notifications are deliveries to systems you don't control, on paths that can retry. The duplicate that reaches a customer is more visible than almost any other bug.

Automate the Fix or Remove the Need

A recurring manual repair is a bug report written in someone's calendar. Building a faster way to perform it is progress; not needing it is the actual goal.

The Admin Tool Is Production

Internal tools get built quickly, reviewed lightly, and given more power than anything customers can touch. They deserve the standards the customer-facing paths get.

A Timestamp Without a Zone Is a Guess

Storing when something happened is easy. Storing it in a way that still means the same thing in another country, six months later, is where systems quietly go wrong.

The Scheduled Job That Ran Twice

Recurring work looks simple until you ask what happens when a run is late, overlaps the next one, or fires on a machine that thinks it's a different hour.

Two Clocks Never Agree

Every machine's clock is slightly wrong, and they're wrong in different directions. Code that compares timestamps across machines is trusting a consensus that doesn't exist.

Hiding the Button Is Not a Check

Where a permission is enforced matters more than how it's modeled. Interfaces hide options; only the layer that touches data can actually deny anything.

Permissions Are a Product Decision

Access control gets treated as plumbing and built by whoever drew the short straw. It's actually a description of how your customers' organizations work.

Someone Has to Be Able to Answer This

"Who can see this record, and why?" is the question a permission system exists to answer. If nobody can answer it without reading code, the system has already failed.

They Changed It and You Didn't Deploy

Your code is identical to yesterday's and the behavior is different, because the change happened on the other side of an integration you don't control.

The Message That Can Never Succeed

Most queue failures are transient and retrying fixes them. The interesting case is the message that will fail identically forever, and what your system does when it meets one.

The ALTER Statement Is the Easy Part

Changing a table's definition takes one line. Getting millions of existing rows into the new shape, while the system keeps running, is the actual project.

The Schema Outlives the Code

Applications get rewritten, frameworks get replaced, services get split apart. The data usually survives all of it, which is why the schema is the most expensive decision in the system.

Write Down What the Data Means

A column name tells you what something is called. It rarely tells you what counts, what's excluded, or which of three plausible definitions the number actually uses.

Logs Are Written for the Wrong Reader

Most log lines are written by someone who already knows what the code does, for a reader who doesn't and won't be able to ask.

Config Changes Are Deploys

A config edit can change production behavior as completely as a code change can, and in most places it does so with none of the review, testing, or staged rollout that code gets.

Every Setting Is a Deferred Decision

Most config options exist because someone couldn't decide, or didn't want to. The knob ships, the decision never gets made, and everyone downstream inherits the question.

The Response Is Part of the Alert

An alert that fires correctly and leaves the person receiving it with no idea what to do has done half a job. The response isn't downstream of the alert — it's the reason the alert exists.

A Rollback Is Not a Time Machine

Rolling back a deploy feels like undoing it. Mostly it undoes the code. Everything the bad code already did to your data, your queues, and your downstream systems is still there, waiting.

A Retry Is a Second Request

Retrying a failed operation feels like giving it another chance to succeed. What it actually does is ask a question nobody thought to answer: what happens if the first attempt worked and the failure was just in hearing about it?

Design the Retry, Not Just the Request

Most operations get designed once, for the happy path, and retries get bolted on after as an afterthought. Treating the retry as part of the operation's design from the start closes most of the gaps this thread has described.

A Cache Is a Promise You Might Break

Every cache makes an implicit promise: this value is still true. The performance win is real, but so is the risk you're quietly signing up for every time you decide not to check.

Cache the Boring Way First

Clever caching strategies solve problems most systems don't have yet, and create ones most systems can't afford. The boring cache — short TTL, simple key, easy to reason about — is usually the right amount of cleverness.

The Cache Key Is the Spec

A cache key is a claim about what makes two requests the same. Get that claim slightly wrong and the cache doesn't fail loudly — it just quietly serves the wrong answer to someone.

Build for Now, Instrument for Later

You can't design for a scale you don't have yet without paying for flexibility you may never use. What you can do is build honestly for today and leave yourself a way to notice the exact moment today stops being enough.

The Shape Hiding in the Loop

Code that looks like it does one pass over the data can secretly do one pass per item — a hidden multiplication that's invisible at small size and unmissable once the input grows.

A Test Proves One Thing

A green test suite feels like a broad statement about your code's health. It's actually a narrow one: these specific inputs produced these specific outputs, today. Confusing the two is where false confidence comes from.

Tested Is Not the Same as Verified

A test that runs and passes tells you the code did what the test checked. It doesn't tell you the test checked the right thing. That second question is easy to skip and expensive to skip.

The Test You Didn't Write

Every test suite has a shadow: the tests that don't exist because nobody thought to write them. That absence doesn't show up on a coverage report, which is exactly why it's where the real risk tends to live.

Deprecate Like You Mean It

A deprecation notice that nobody acts on isn't a warning, it's decoration. The gap between marking something deprecated and actually being able to remove it is where most interfaces quietly calcify.

The Contract Is What They Rely On

You decide what your interface promises. Your users decide what they depend on. When those two differ — and they always do — the second one is the real contract.

Version the Promise, Not the Code

A version number is supposed to tell callers something. Too often it just tells them the code changed — which they already knew, and which doesn't help them decide whether to worry.

Every Error Is a Design Decision

Error handling gets treated as the cleanup after the real work — the branch you fill in to make the compiler happy. But what a system does when something goes wrong is part of what the system is.

One Wrong Default, Times Everyone

A bug in a rarely-used option affects the people who chose it. A bug in the default affects everyone who didn't choose anything — which is usually almost everyone. The blast radius of a mistake tracks how many people never had to opt in.

The Default Is a Decision

Defaults feel like the absence of a choice — the value nobody had to set. In practice they're the choice most users will live with, made once by someone who won't be there to see the consequences.

The Setting Nobody Should Need

Adding a setting can be a way of avoiding a decision — shipping both answers instead of finding the right one. Sometimes that's respect for real variation. Sometimes it's an unresolved argument, permanently installed.

The Code You Can't Loop On

Some code has no fast feedback loop at all — you can't easily run it, watch it, or reproduce its failures. That code doesn't just move slowly. It resists being understood, and the slowness compounds.

The Loop Is the Unit of Speed

How fast you build isn't set by how fast you type. It's set by how quickly you can go around the loop of making a change, seeing what it did, and learning from it. That cycle time is the real speed.

The Flexibility You Didn't Need

Building for an imagined future feels like foresight. Usually it's a bet against odds you'd never take if you saw them clearly: pay the cost of flexibility now, on a guess about needs that mostly never arrive.

The Simplest Thing That Works

If code is a liability and speculative flexibility is a bad bet, the discipline that follows is to build the simplest thing that solves today's real problem. The hard part is telling simple from naive.

The Comment That Should Have Been Code

The urge to write a comment explaining what a piece of code does is usually a signal, not a solution. Most of the time the honest fix is to make the code say it — and a comment is what you write only when the code can't.

The Cost of Surprise

Code that works but behaves unexpectedly still charges a tax: every reader has to stop and verify the thing they assumed. Consistency isn't aesthetic tidiness — it's what lets people trust their assumptions and move on.

The Name Is the Understanding

Struggling to name something isn't a vocabulary problem. It's the code telling you that you don't yet understand the thing you're building — and a good name is what understanding looks like once you do.

The Second Ninety Percent

The old joke — the first 90% of the work takes 90% of the time, and the last 10% takes the other 90% — isn't cynicism. It's a precise description of where estimates go to die: the unglamorous finishing that no one pictures.

Coverage Is Not Confidence

A coverage number tells you which lines ran during the tests. It says nothing about whether anything was actually checked — and the gap between those two is where teams get a false sense of safety.

The Mock That Agreed With You

A mock replaces a real dependency with your belief about how it behaves. When the belief is wrong, the test passes and production fails — because you tested the version of the world in your head, not the one that exists.

The Test That Broke for the Wrong Reason

A test that fails when you refactor working code isn't protecting you — it's charging you. And the real damage isn't the wasted hour; it's that the suite slowly teaches people that failures don't mean anything.

The Code Outlives the Reason

Code persists perfectly; the reasoning behind it evaporates. Which is why so much of a mature codebase is lines nobody dares touch — not because they're wrong, but because nobody remembers what they were for.

The Rewrite Is a Knowledge Bet

Rewriting feels like replacing bad code with good code. It's really replacing accumulated knowledge with a fresh guess — and the ugliness you're removing is often where that knowledge is stored.

Make the Bad State Impossible

Checking for invalid states at runtime means remembering to check everywhere. Shaping your data so the invalid state can't be expressed at all means you only have to be right once — at the type, not at every call site.

State Is the Hard Part

Computation is mostly easy; the hard part of software is state — the accumulated memory of everything that happened before. Most bugs aren't wrong logic, they're the system being in a combination of states nobody pictured.

Two Copies of the Truth

The moment a fact lives in two places, you've taken on a job you'll eventually fail at: keeping them equal. Most 'impossible' bugs are just two copies of something that were supposed to agree and quietly stopped.

Draw the Line Where It Changes

A module boundary is a bet about what will change together. Draw it along the axis of change and edits stay local; draw it along surface resemblance and every change cuts across every module.

The Abstraction That Leaks

Every useful abstraction hides the layer beneath it — until the day it can't. The ones that serve you longest aren't the ones that hide the most, but the ones that fail honestly when the thing underneath breaks through.

Wait for the Third Case

The wrong abstraction is more expensive than duplication, because it's harder to reverse. Which is an argument for waiting — abstracting on the third occurrence, not the first, when you finally know which parts actually vary.

The At-Least-Once Default

Most messaging systems promise to deliver each message at least once, not exactly once. The gap between what you assumed and what the system actually guarantees is where the duplicate-processing bugs live.

The Idempotency Requirement

The moment you add retries to a system, you've made a promise you might not be keeping: that doing the same operation twice is the same as doing it once. Idempotency is what makes that promise true.

The Ordering Assumption

Messages arrive in the order they were sent — until they don't. Assuming global ordering in a distributed system is one of those beliefs that holds in testing and breaks in production, quietly, in ways that are hard to trace.