First principles thinking means breaking a problem down to its irreducible truths and reasoning upward from there — instead of inheriting answers from what already exists. This page lays out how we want to approach hard problems together: the method, the questions, the examples from our world, and the failure modes to watch for.
Over two thousand years ago, Aristotle called a first principle "the first basis from which a thing is known." In every systematic inquiry, he wrote, we acquire knowledge by working back to primary causes. Descartes restated it in the 17th century with his method of doubt: peel away every assumption you can possibly doubt until what remains is indubitable, and rebuild from there.
Modern proponents — Musk at SpaceX, Bezos at Amazon, Charlie Munger across decades of investing, and Richard Feynman in physics — all describe the same move: drop the inherited frame, list what's actually true, and rebuild. Most people don't. Most people, in Musk's phrase, "live life by analogy" — they project the current form forward instead of asking what function it has to serve.
Analogy is borrowed knowledge — fast, usually correct, useless when the situation is genuinely new. First principles is derived knowledge — slow, harder, the only thing that works when the analogy breaks.
Map a new problem onto an old, familiar one and inherit its answer. Cheap to do, often right — until the analogy breaks.
List the irreducible facts of the situation, then build the answer up from there. Expensive — but you stop inheriting someone else's mistakes.
First principles isn't a vibe — it's a procedure. The same four steps work whether you're choosing a database, debugging a flaky test, or proposing an architecture change.
State the outcome in plain language — not the solution. A solution dressed as a problem will lock you into the analogy you're trying to escape.
Break the problem into the smallest pieces you're sure are true. Constraints, requirements, physical limits, data shape. Anything else is an assumption.
For every "atom," ask: is this a fact, a constraint, or a convention? Conventions can be moved. Constraints can sometimes be renegotiated. Facts are the floor.
Compose a solution out of only the atoms you trust. If your result looks like the conventional answer, fine — you've earned it. If it doesn't, you've found something.
These are the questioning techniques that actually get a room down to the floor. Use them inside the four-step method — they're the how, not a replacement for it.
A disciplined sequence of questions that exposes assumptions and tests reasoning. The point isn't to win — it's to surface what's actually believed.
Take the visible problem and ask "why" until the answer stops moving — usually around the fourth or fifth pass. The honest endpoint is often "I don't know." That's the discovery.
Explain the thing in plain language, as if to a smart 12-year-old. Wherever you reach for jargon, you've found a gap. Fill it. Re-explain. Repeat.
Don't ask "how do I make this succeed?" — ask "how would I guarantee this fails?" Then refuse to do those things. The fastest way to be smart is to stop being stupid.
Most of these aren't dramatic. They're the small, daily decisions where teams quietly inherit someone else's answer. The win isn't always a rewrite. Sometimes it's a smaller scope, a deleted system, or just a different question in the design review.
"Netflix and Amazon use microservices. We're scaling, so we should split too."
What are the actual coupling boundaries in the code? What independent deploy pressure exists? What's the team topology? Microservices solve organizational scaling, not request volume.
A 12-person team rediscovers that a well-modularized monolith plus one extracted service beats 14 microservices nobody owns.
"This endpoint is slow. Put Redis in front of it. Every fast site has caching."
What does the endpoint actually do? Why is it slow — N+1, missing index, oversized payload, sync work that could be async? A cache often hides the cause and becomes a permanent dependency.
You add one index. p95 drops 8×. You never deploy Redis. The cache invalidation bug you would have shipped never exists.
"There's a SaaS for that. We pay $X/mo and avoid distraction." (Or the inverse: "We can build it in a weekend.")
What is core to our business and what is plumbing? What does the vendor actually do — data ingestion, retention, dashboards — and what would the in-house equivalent cost in ongoing maintenance, not just initial build?
You keep the vendor for analytics (commodity) and build the pricing engine in-house (proprietary). The opposite of what the loudest argument suggested.
"Use Postgres." Or: "We have time-series-ish data — use a time-series DB."
What's the read pattern? Write pattern? Consistency model required? Cardinality? Query shape? "Postgres" is usually right because it's flexible — but you should be able to say why for your shape, not just inherit it.
You still pick Postgres — but with deliberate choices about partitioning, indexes, and a clear migration story you didn't have before.
"It's flaky. Retry it three times in CI. Everyone does that." (Or: @flaky annotation.)
A flaky test is a true statement about your system — it says something is non-deterministic. What state is shared? What timing assumption is encoded? Five whys until you find the actual race.
You find a shared mutable singleton three layers down. The "flake" was a real production bug under load — you just hadn't been paged yet.
"REST with these resources, because that's how Stripe does it. Or GraphQL, because Shopify."
Who calls this and how often? What does the caller need to know — and not know — to be successful? What invariants does the API have to preserve regardless of client behavior? Style follows from that.
Half the endpoints collapse. The remaining ones model intent (/refund) rather than data (PATCH /payment) — and the clients get simpler.
"It's the industry standard. Everyone runs on k8s. We'll look unprofessional without it."
What problem does k8s solve — multi-tenant scheduling, declarative ops, portable workloads? Do we have those problems right now, or in the next 18 months? What does the maintenance cost look like at our team size?
You stay on managed containers for another year, ship features instead of YAML, and revisit k8s when your team is 3× larger and the actual constraints have arrived.
First principles is expensive. Used everywhere, it grinds the team to a halt — used nowhere, you inherit drift. The job is to apply it where the stakes justify the cost: hard-to-reverse decisions, recurring problems, anything with the word "always" attached.
For any non-trivial design doc, require these four sections — in order. The order matters. Solutions before atoms is how analogies sneak in.
A 60-minute workshop format that works for architecture decisions, incident retros, and "why does this keep happening?" loops.
Drop these into design reviews, retros, and 1:1s. They're cheap, they don't require a workshop, and they shift the room without confrontation.
First principles dies fast in a low-trust room. The method only works if people can say "I don't know" without paying for it socially. Specifically:
The technique is powerful enough that it earns its own warning label. Most failure modes share a root cause: confusing "I have not understood this" with "this has no reason to exist."
That weird middleware, that retry loop, that null check — all were put there by someone solving a real problem. First principles is the right to remove them after you've understood them, not before.
The standard solution often is the first-principles answer — proven by ten thousand teams before you. Rederiving Postgres is a thought exercise, not a deliverable.
If you don't pre-commit to a depth and a deadline, the method becomes a way of avoiding the decision rather than making it. Pick a budget. When it's up, ship the best answer you have.
"Users want X." "Latency must be under 100ms." "We can't break this API." These feel like facts and are usually constraints — sometimes negotiable ones. Mark them as such.
The technique cuts through groupthink — but only with a group. Run it alone and you'll just rederive your own priors with extra steps. Get adversarial readers.
Naming a variable, fixing a typo, picking a logging format — analogy is fine, analogy is good. Save first principles for decisions you'll have to live with for a year.
First principles is one mental model. Munger's point was that you want a latticework — overlapping models that catch each other's blind spots. These are the ones that pair best for engineering work.
After you derive the answer, ask: "How would I guarantee this fails?" If your design quietly answers yes to several of those, your atoms were incomplete.
First-order thinking stops at the immediate effect. Second-order asks what happens once the world adapts to your change. The cache works — and then everyone codes against the cache, and then…
The guard rail against first-principles arrogance. Every weird thing in your codebase had a reason. First derive that reason, then decide whether it still holds.
Explain your design to someone three layers removed. Wherever you hit jargon, you've found a hole in your own reasoning, not theirs.
Before you "win" the decision, build the strongest version of the position you're rejecting. If you can't, you haven't done the work.
The corollary to "rebuild from atoms": don't add atoms that aren't required yet. First principles makes you derive what's needed — YAGNI keeps you from deriving what isn't.
We don't adopt first principles by reading about it. We pick one real decision on our plate this week — a database choice, a refactor, a vendor, a retry policy — and we run it through the method together. Frame the goal. List the atoms. Challenge each. Rebuild. See what survives.
If it works, we'll do it again. If it doesn't, we'll know what broke and adjust. That's the whole onboarding.