tl;dr: “Beware of bugs in the above code; I have only proved it correct, not tried it.” –Donald Knuth
We call ourselves software “engineers.” Yet any sincere “engineer” who wrote more than 10,000 lines of code will tell you “engineering” has very little to do with what we do. We’re mostly duct-taping things.
Before building a bridge, a bridge engineer1 computes stress, strain and deflection in their beams2. A software “engineer” just starts writing code. A bridge engineer operates with a safety margin: the bridge should resist 2x to 4x the maximum expected load. A software “engineer” continues writing more code. Some of this code may be tested, for some input values, but that’s about it. A bridge engineer signs off on their design3 and is subject to professional negligence lawsuits if they seriously mess up4$^,$5. A software “engineer” just ships the code.
The net result of our “engineering” practice? Years later, when that code leaks your phone number, home address and the names of all your family members, the “engineering” company is “deeply sorry.” This happens several times per year now6.
A more honest name for our practice should be “software carpentry.” It recognizes that, while we do have a skilled craft, safety calculations hardly enter into it. My thesis is simple (and, I hope, hardly controversial by now): to graduate from “software carpentry” to “software engineering”, it would be sufficient for us to embrace formal verification7.
Luckily, in the LLM age, we could actually do this. Formal verification is becoming easier to apply to increasingly larger projects8. The first step is to apply formal verification to our less complex software, software with clean interfaces that admits small specifications. In other words, formal verification for our building blocks:
- “this library sorts”9
- “this binary zips”10
- “this is a EUF-CMA signature scheme implementation with no side-channels”
Then, we could push the boundary beyond simple buildings blocks to more complex systems:
- “this query optimizer produces a plan semantically equivalent to the unoptimized query”
- “this consensus protocol satisfies safety and liveness under \(f < n/3\) Byzantine faults”11
If we did so, there’d be many advantages:
- We can safely unleash AI to optimize our codebase.
- This requires progress in compiling (say) Lean programs to be faster.
- Or, it requires what has been referred to as “the final form of software development”12 to manifest.
- Folks are barely reviewing AI-generated code anyway. Formal verification can enable them to safely not do so.
- Instead of tests that cannot cover all executions with all values13, we prove all executions perform what we expect them to.
- Instead of repeated, error-prone (LLM/manual) audits on our ever-changing, large codebases, we can reduce audit scope to the specs, which are implementation-agnostic.
- Instead of trusting that an imported dependency does something, we don’t; we update our proof after integrating the dependency. If the proof passes, then program only does what the spec says.
- The only part will be a bit tricky, but doable.
There already is plenty of encouraging work showcasing the viability of formal verification (pre-LLM age):
- seL4, an entire OS microkernel, proven functionally correct14.
- CompCert, a full C compiler, proven to preserve program semantics from source to assembly15.
- IronFleet, a Paxos-based replicated state machine plus a lease-based sharded key-value store, with proofs of both safety and liveness16.
- Everest TLS stack, a formally verified TLS implementation (miTLS), covering the full protocol state machine, not just the handshake crypto17.
- AWS’s use of TLA+, not a proof of an entire system, but industrial-scale application of formal methods to distributed systems bugs at production complexity18.
As caveated above, formal verification will not be a panacea:
- Some software can be as complex to specify as it is to implement (e.g., EC2 cloud architectures come to mind).
- Software evolves, not just in its implementation, but also in its specification.
- Formal verification rarely covers the full system $\Rightarrow$ bugs creep in in uncovered parts.
- For example, seL4 had bugs due to timing channels19.
- CompCert had bugs in its unverified parts: parsing bugs that produced a bad abstract syntax tree (AST), since the formal verification only modeled compilation from the AST20, but also bugs in its C elaborator, in its Win64 ABI model and in its assembly printer21.
- Formally-verified systems are often compiled with an unverified compiler
- Formally-verified systems often execute in an unverified environment: the operating systems, the x86_64 CPU, etc.
- The formal verification framework/language may itself have soundness or completness issues22.
So, if you are tired of being a carpenter whose chairs keep breaking “for no reason,” what other options do you have?
References
For cited works, see below 👇👇
-
As of 2026, we’ve been questioning the “engineering” in “software engineering” for almost 30 years. See this old comp.lang.ada USENET convo from 1997. ↩
-
Stress, Strain, and Deflection in Beams, a chapter in a structural engineering textbook. ↩
-
Texas Occupations Code § 1001.401 - Seal Required, Texas Statutes, current ↩
-
Chapter 150, Texas Civil Practice and Remedies Code — Certificate of Merit requirement, discussed in Texas Court of Appeals case citing Ch. 150 ↩
-
Carlson, Brigance & Doering, Inc. v. Compton — Texas Appellate Court on Certificate of Merit and vicarious liability, LGWM Law summary of Tex. App. decision, Dec. 8, 2020 ↩
-
Why does it matter if everyone can find out where you live, you ask? Try doing anything of significance in today’s world and you’ll get a “fan club” in no time. ↩
-
Not saying it is necessary to. Only saying it would be sufficient to. ↩
-
Formal verification and AI, by Martin Kleppmann, 2025 ↩
-
“Just Lean: a verified, fast sort”, by Gregor Mitscha-Baude ↩
-
“Why Lean is faster than Rust”, by Kim Morrison, July 24th, 2026 ↩
-
Okay, fine: maybe safety and liveness specs for consensus protocols will not exactly be small. ↩
-
“The end of coding as we know it”, by zkSecurity ↩
-
How to misuse code coverage, by Marick, Brian and Smith, John and Jones, Mark, in Proceedings of the 16th Interational Conference on Testing Computer Software, 1999 ↩
-
seL4: formal verification of an OS kernel, by Klein, Gerwin and Elphinstone, Kevin and Heiser, Gernot and Andronick, June and Cock, David and Derrin, Philip and Elkaduwe, Dhammika and Engelhardt, Kai and Kolanski, Rafal and Norrish, Michael and Sewell, Thomas and Tuch, Harvey and Winwood, Simon, in Proceedings of the ACM SIGOPS 22nd symposium on Operating systems principles, 2009, [URL] ↩
-
Formal verification of a realistic compiler, by Leroy, Xavier, in Communications of the ACM, 2009, [URL] ↩
-
IronFleet: proving practical distributed systems correct, by Hawblitzel, Chris and Howell, Jon and Kapritsos, Manos and Lorch, Jacob R. and Parno, Bryan and Roberts, Michael L. and Setty, Srinath and Zill, Brian, in Proceedings of the 25th Symposium on Operating Systems Principles, 2015, [URL] ↩
-
Everest: Towards a Verified, Drop-In Replacement of HTTPS, by Bhargavan, Karthikeyan and Bond, Barry and Delignat-Lavaud, Antoine and Fournet, Cédric and Hawblitzel, Chris and Hritcu, Catalin and Ishtiaq, Samin and Kohlweiss, Markulf and Leino, Rustan and Lorch, Jay and Maillard, Kenji and Pang, Jinyang and Parno, Bryan and Protzenko, Jonathan and Ramananandro, Tahina and Rane, Ashay and Rastogi, Aseem and Swamy, Nikhil and Thompson, Laure and Wang, Peng and Zanella-Béguelin, Santiago and Zinzindohoué, Jean-Karim, in SNAPL 2017 - 2nd Summit on Advances in Programming Languages, 2017, [URL] ↩
-
How Amazon Web Services uses formal methods, by Chris Newcombe and Tim Rath and Fan Zhang and Bogdan Munteanu and Marc Brooker and Michael Deardeuff, in Communications of the ACM, 2015, [URL] ↩
-
The Last Mile: An Empirical Study of Timing Channels on seL4, by Cock, David and Ge, Qian and Murray, Toby and Heiser, Gernot, in Proceedings of the 2014 ACM SIGSAC Conference on Computer and Communications Security, 2014, [URL] ↩
-
Finding and understanding bugs in C compilers, by Yang, Xuejun and Chen, Yang and Eide, Eric and Regehr, John, in ACM SIGPLAN Notices, 2011, [URL] ↩
-
“How We Found Three Bugs in a Compiler Proven Correct”, by Cantina, August 18th, 2026. None of the three bugs contradicted CompCert’s correctness theorem: they were in the unverified parts around it (the C elaborator, the Win64 ABI/register-allocation model, and the assembly-printing stage, where a newline in a source filename could inject arbitrary ARM instructions). ↩
-
“Postmortem for Kernel Soundness Bug #14576”, by Leonardo de Moura, August 1st, 2026 ↩
