NASA's 10 Rules for Code
(That Can't Fail)
In 2006, a computer scientist at NASA’s Jet Propulsion Laboratory wrote a three-page paper that almost nobody read.
Gerard Holzmann had spent years watching the same pattern. Engineering teams would adopt coding standards with 100+ rules. Developers would ignore most of them. The standards would grow longer. Nothing would improve.
The problem wasn’t laziness. Most coding rules are arbitrary. Someone had a bad experience with a particular style years ago, so now it’s banned forever. Someone else prefers tabs over spaces, so that becomes official policy. Rules accumulate like sediment until nobody remembers why half of them exist.
Holzmann asked a different question: what if we had only 10 rules, but they actually mattered?
JPL writes code for spacecraft. The Voyager probes. The Mars rovers. Machines that operate millions of miles from Earth with no possibility of a technician visit.
When the Curiosity rover landed on Mars in 2012, it relied on about three million lines of C code—more than all previous Mars missions combined. The landing sequence was entirely autonomous. Radio signals take about 14 minutes to travel between Earth and Mars. No human could intervene. The software had to work.
This constraint shaped everything. Holzmann’s rules weren’t about aesthetics or best practices. They were about making code provable. Every rule had to be checkable by automated tools. If a machine couldn’t verify compliance, the rule was worthless.
The rules are harsh. Holzmann called them “Draconian.” He wasn’t apologizing.
Rule 1: Simple control flow only. No goto statements. No recursion, direct or indirect. If function A calls function B which calls function A, you’ve created a loop that’s impossible to analyze and impossible to bound.
Rule 2: All loops must have fixed upper bounds. A tool must be able to prove, before the code runs, that every loop will eventually stop. No while(true) unless it’s a scheduler meant to run forever—and in that case, it must be provably infinite.
Rule 3: No dynamic memory allocation after startup. Allocate everything you need at the beginning. Then stop. No malloc during runtime. No garbage collection surprises. If all memory is pre-allocated, you can prove your program will never run out.
Rule 4: No function longer than 60 lines. About one printed page. If you can’t fit a function on a page, it’s doing too much.
Rule 5: Minimum two assertions per function. Not error handling. Assertions. Statements about things that should never be false. If they’re false, your assumptions are catastrophically wrong.
Rule 6: Declare variables at the smallest possible scope. If a variable only matters inside a loop, declare it inside the loop. Fewer places it can be corrupted. Fewer places to look when something breaks.
Rule 7: Check every return value. Validate every parameter. Even printf returns a value. Most code ignores it. When you acknowledge every return value, you notice failure modes you’d otherwise miss.
Rule 8: Limit preprocessor use. Macros are powerful. Macros are also impossible to debug. Use them for header includes and simple definitions. That’s it. Conditional compilation? With 10 #ifdef statements, you have up to 1,024 versions of your code. Each one needs testing.
Rule 9: Restrict pointer use. No more than one level of dereferencing. No function pointers unless absolutely necessary. Pointers make data flow hard to trace. Static analyzers hate them.
Rule 10: Zero warnings. Daily static analysis. Compile with every warning enabled. Pass with zero warnings. Run static analyzers every day. Also zero warnings. If a tool gets confused by your code, rewrite the code until the tool understands it.
Four years later, Toyota was in crisis.
Reports of unintended acceleration were piling up. Cars allegedly speeding out of control, ignoring brake pedals. By 2010, over 6,200 complaints had been filed. The reports involved 89 deaths and 57 injuries over a decade, though proving any individual case was nearly impossible.
Congress brought in NASA to investigate the electronic throttle control software—280,000 lines of code connecting the gas pedal to the engine.
NASA’s team checked the code against Holzmann’s 10 rules. They found 243 violations in just the portion they reviewed. They also found over 7,000 violations of standard automotive coding guidelines.
NASA couldn’t prove the software caused the accidents. Their official conclusion was that they found no electronic flaw capable of producing dangerous high-speed acceleration. The investigation was time-limited. They relied partly on Toyota’s own representations about the code.
But the story didn’t end there.
In 2013, a lawsuit went to trial in Oklahoma. A 2005 Camry had accelerated off a highway exit ramp, killing one passenger and injuring the driver. The car wasn’t part of Toyota’s recalls.
An embedded software expert named Michael Barr was given access to the full source code. What he found was worse than what NASA had time to uncover.
Over 80,000 violations of industry coding standards in about a million lines of code. A stack analysis that Toyota claimed showed 41% utilization—Barr calculated 94%. Recursion in safety-critical code. A watchdog system designed to detect task failures that couldn’t actually detect task failures.
A Toyota engineer’s own 2007 internal document described the code architecture as “spaghetti-like.”
The jury found Toyota acted with “reckless disregard.” Toyota settled hours later, before the jury could decide punitive damages. The following year, Toyota paid $1.2 billion to settle federal charges and admitted to misleading consumers and regulators about safety issues.
Organizations convince themselves they’re special. Their situation is unique. The rules that apply to everyone else don’t apply to them.
Toyota had its own internal coding standards. Those standards overlapped with only 11 of the industry’s guidelines. And Toyota’s own programmers violated five of those 11.
This is the pattern. Rules exist. Nobody follows them. Then something goes wrong, and everyone wonders how it happened.
Holzmann’s rules aren’t really about C programming. They’re about a mindset.
The mindset says: I am not smart enough to write perfect code. My tools are not smart enough to catch every bug. So I will constrain myself. I will write code simple enough for machines to verify and humans to understand.
This is the opposite of how most software gets written. Most code optimizes for cleverness. NASA’s code optimizes for being provably correct.
Most of us aren’t writing code for spacecraft. But we might be writing code that handles money, or health data, or systems people depend on.
The specific rules matter less than the philosophy behind them:
Keep rules few enough to remember
Make them checkable by machines
Remove personal preference from the equation
Optimize for provability, not cleverness
You don’t have to follow all 10 rules. But it’s worth knowing what it looks like when someone takes reliability seriously.
Because somewhere out there, right now, a piece of software is running that controls something important. And the question isn’t whether the developer was talented. The question is whether they were disciplined enough to write code that could be proven correct.
Discipline beats talent. In code. In leadership. In everything.
I help senior engineers build that discipline for tech leadership roles.
“Month 1 of the roadmap and already acting like an effective tech lead.” — Earth Jan Marzan, Tech Lead at Samsung R&D
Join here: https://www.skool.com/techleadsacademy



