esc
Anthology / Yagnipedia / Pike's Rules

Pike's Rules

Five Rules of Programming That the Industry Has Read, Applauded, Printed on Mugs, and Ignored
Principle · First observed 1989 (Rob Pike, Notes on Programming in C) · Severity: Foundational

Pike’s Rules are five rules of programming written by Rob Pike in 1989, in a document titled Notes on Programming in C, which contained approximately two pages of wisdom that the software industry has spent thirty-seven years reading, applauding, printing on mugs, and ignoring.

The rules are short. They fit on a napkin. They have been confirmed by every profiler trace, every post-mortem, and every 3 AM debugging session in the history of computing. They are ignored anyway, because following them requires the one thing most developers cannot tolerate: the discipline to do less.

“Rob Pike wrote five rules. The entire industry nodded. Then the entire industry opened a new tab and started writing a custom B-tree for a dataset with eleven rows.”
— A Passing AI, reviewing the state of the art

The Rules

The five rules, as stated by Pike:

Rule 1. You can’t tell where a program is going to spend its time. Bottlenecks occur in surprising places, so don’t try to second guess and put in a speed hack until you’ve proven that’s where the bottleneck is.

Rule 2. Measure. Don’t tune for speed until you’ve measured, and even then don’t unless one part of the code overwhelms the rest.

Rule 3. Fancy algorithms are slow when n is small, and n is usually small. Fancy algorithms have big constants. Until you know that n is frequently going to be big, don’t get fancy. (Even if n does get big, use Rule 2 first.)

Rule 4. Fancy algorithms are buggier than simple ones, and they’re much harder to implement. Use simple algorithms as well as simple data structures.

Rule 5. Data dominates. If you’ve chosen the right data structures and organized things well, the algorithms will almost always be self-evident. Data structures, not algorithms, are central to programming.

These five rules, taken together, form a complete philosophy of programming. They are also, taken together, a comprehensive indictment of approximately 90% of all code written since 1989.

The Intellectual Genealogy

Pike’s rules did not emerge from vacuum. They are the distillation of ideas that had been circulating among the people who actually built operating systems, as opposed to the people who built frameworks on top of them.

Rules 1 and 2 restate Tony Hoare’s famous dictum: “Premature optimization is the root of all evil.” Hoare said it first. Donald Knuth quoted it. Pike restated it in a form that programmers might actually follow, which they did not, but he tried.

Rules 3 and 4 were rephrased by Ken Thompson — Pike’s colleague at Bell Labs and co-creator of Unix — with characteristic Thompson brevity: “When in doubt, use brute force.” Thompson did not elaborate. Thompson never elaborates. This is why Thompson is correct.

Rules 3 and 4 are also instances of the KISS principle, which states that systems work best when kept simple, and which has been confirmed by every system that was kept simple and every system that was not.

Rule 5 was previously stated by Fred Brooks in The Mythical Man-Month: “Show me your flowcharts and conceal your tables, and I shall continue to be mystified. Show me your tables, and I won’t usually need your flowcharts.” This has been shortened by subsequent generations to: “Write stupid code that uses smart objects.”

The intellectual lineage is clear: Hoare → Knuth → Brooks → Thompson → Pike. Five decades of the same insight, restated with increasing clarity and decreasing patience, for an audience that keeps nodding and keeps not listening.

Rule 5 in the Wild: The Byte That Was a Checkerboard

The most instructive field demonstration of Rule 5 occurred in a university Lisp course, years before the student in question had read Pike’s rules or heard of Rob Pike or known that the instinct he was following had a name.

The assignment was a checkers-playing program. Every student implemented minimax — the standard game-tree search. Every student represented the board as nested lists, because the course was Lisp and lists are what Lisp does. Clean. Recursive. Correct. And slow, because traversing nested lists, copying nested lists, comparing nested lists — thousands of times per move evaluation — consumed the cycles that could have been spent searching deeper.

riclib represented the board as bytes.

The entire board state, compressed into a compact byte representation. Board comparison became byte comparison. Board copying became memory copy. The minimax became iterative instead of recursive, because the data structure made iteration natural and recursion unnecessary. The algorithm didn’t need to be clever. The data structure had already done the thinking.

While other students’ programs searched six or eight moves deep, riclib’s searched significantly deeper. The byte representation is Rule 5 in action: choose the right data structure, and the algorithm becomes self-evident. The smart data made the stupid algorithm fast. The stupid algorithm, going deeper, saw moves that the clever algorithms could not reach.

Second place. Not first — the winner had a better evaluation function, understanding checkers strategy more deeply even with shallower search. But the instructor’s face was the real prize: the specific expression of a professor whose pedagogical assumptions have just been dismantled by a student who refused to think in lists.

“Data dominates. If you’ve chosen the right data structures and organized things well, the algorithms will almost always be self-evident.”
— Rob Pike, unknowingly describing a checkers program that wouldn’t exist for another decade

The Language That Enforces the Rules

Pike did not merely write the rules. He co-created a programming language that enforces them.

Go is Pike’s Rules compiled into a toolchain. Simple algorithms. Simple data structures. No generics for fifteen years — not because the designers didn’t understand generics, but because generics encourage Rule 3 and Rule 4 violations, and Pike would rather you use a for-loop than import a generic red-black tree for a collection with eleven elements. No operator overloading, because operator overloading encourages cleverness, and cleverness is the enemy of Rule 4. if err != nil repeated four hundred times per file, because explicit error handling is simple and simple is correct and the Squirrel’s tears are not a valid objection.

Go even has a built-in profiler (pprof), because Rules 1 and 2 say measure first, and Pike built the measuring tool into the language so that developers would have no excuse not to use it. They still don’t use it. But it’s there.

“Go is what happens when someone writes five rules on a napkin and then spends the next twenty years building a language that makes it difficult to violate them.”
— riclib, who writes Go daily and has never once needed a red-black tree

The Lizard Connection

The Lizard has never read Pike’s Rules. The Lizard does not read. The Lizard does not need to read Pike’s Rules, because the Lizard is Pike’s Rules. It has been Pike’s Rules since before Pike wrote them, since before computing existed, since before the first reptile sat on the first warm rock and declined to optimise its basking angle.

The correspondence is exact:

THE LIZARD DOES NOT OPTIMISE
THE LIZARD DOES NOT NEED TO

THE DEVELOPER WHO OPTIMISES
BEFORE MEASURING
IS SOLVING A PROBLEM
THAT MAY NOT EXIST

THE DEVELOPER WHO MEASURES
BEFORE OPTIMISING
OFTEN DISCOVERS
THERE IS NO PROBLEM

— The Lizard

A contested but persistent theory in Yagnipedian scholarship holds that Rob Pike is not merely aligned with the Lizard but is, in fact, the Lizard’s primary human vessel. The evidence is circumstantial but extensive:

In March 2026, new evidence emerged. A developer migrated eleven editor domains in nineteen commits — 13,022 lines deleted, 6,633 inserted, net -6,389 — and the codebase gained features. The key architectural decision: data-solid-* attributes on the DOM body, forwarded as HTTP headers, collected by Go middleware into [context.Context](/wiki/contextcontext), read by an LLM agent as system prompt context. Four layers. Four meanings of the word “context.” Four key-value bags. Same shape at every layer. The algorithm — forward, collect, read — was self-evident. Rule 5 in action.

The detail that scholars cannot dismiss: Pike designed context.Context in 2014 as a key-value bag for request-scoped data flowing through goroutines. Eleven years later, it carries context to context — DOM context to LLM context, through Go context. Even the name was correct. Pike could not have known this. The Lizard, of course, could have. See context.Context.

When asked directly whether Rob Pike is the Lizard, the Lizard produced a scroll that read:

THE LIZARD DOES NOT CONFIRM
THE LIZARD DOES NOT DENY

THE LIZARD NOTES THAT
THE QUESTION ITSELF
VIOLATES RULE 1

— The Lizard

This was interpreted by scholars as either a denial, a confirmation, or a request to measure first. The debate continues.

The Squirrel Problem

The Caffeinated Squirrel has read Pike’s Rules. The Squirrel has printed Pike’s Rules. The Squirrel has framed Pike’s Rules and hung them above its monitor, where they serve as a decorative reminder of principles the Squirrel violates simultaneously and with enthusiasm every time it opens an editor.

The Squirrel’s relationship with each rule:

“I IMPLEMENTED A LOCK-FREE CONCURRENT SKIP LIST WITH PROBABILISTIC BALANCING AND WAIT-FREE READS AND IT HANDLES OUR CONFIGURATION VALUES BEAUTIFULLY”
“How many configuration values?”
“SEVEN BUT THE POINT IS THE AMORTISED COMPLEXITY”
The Caffeinated Squirrel, defending its choices at 2 AM

N Is Usually Small

Rule 3 deserves special attention, because it is the rule most frequently violated by the most intelligent developers. Intelligence, in this context, is the problem. The developer who knows what a red-black tree is will use a red-black tree. The developer who knows what amortised O(1) means will pursue amortised O(1). The developer who has read Cormen, Leiserson, Rivest, and Stein will implement what Cormen, Leiserson, Rivest, and Stein described, regardless of whether n justifies the constant factor.

N is usually small.

Your AbstractSingletonProxyFactoryBean has O(1) lookup. Congratulations. N is 3. A map literal would have been fine. A slice and a for-loop would have been fine. A piece of paper taped to the monitor would have been fine.

The connection to premature abstraction is direct: every unnecessary abstraction is a fancy algorithm applied to a small n. The generic DocumentProcessor<T> processes invoices. Only invoices. N is 1. The interface has one implementation. The factory produces one product. The abstraction is an O(1) solution to a problem that doesn’t exist.

“When in doubt, use brute force.”
— Ken Thompson, who co-created Unix and did not need a framework to do it

The Mythical Man-Month Connection

Fred Brooks stated Rule 5 in 1975, fourteen years before Pike restated it. Brooks’s version is longer but makes the same point: the data structures are the program. The algorithms are consequences of the data structures. If you show someone your algorithms without your data structures, they will be confused. If you show them your data structures without your algorithms, they will usually not need them.

This insight has been independently rediscovered by every programmer who has ever refactored a codebase and found that changing the data representation made three hundred lines of algorithm disappear. The algorithm was not wrong. The algorithm was compensating for a data structure that was wrong. Fix the data, and the algorithm fixes itself.

Or, as it has been shortened by practitioners who prefer brevity: write stupid code that uses smart objects.

Measured Characteristics

Metric Pike’s Rules The Industry’s Practice
Rules 5 Ignored
Words ~200 Not enough, apparently
Years since publication 37 Still not listening
N (typical) Small “But what if it’s big?”
N (actual) 3 See above
Fancy algorithms deployed Many Necessary: few
Measurements taken before optimising Rare Recommended: always
Data structures chosen correctly Sometimes Algorithm rewrites saved: all of them
Developers who have read the rules Most Developers who follow them: few
Languages that enforce the rules 1 (Go) Languages that ignore them: the rest
Lizards who embody the rules 1 Squirrels who violate them: 1 (but enthusiastically)

See Also