Protocol-first engineering: one fewer layer between you and the failure
Practice · Bare Metal Software
Every abstraction layer between your code and the actual protocol it speaks — HTTP, SQL, a filesystem — is a place a failure can be hidden or a behavior can be misunderstood. Protocol-first engineering asks, for every layer under consideration: would writing the explicit protocol call make behavior clearer, not just shorter? Most vendor SDKs and ORMs fail that test; a well-chosen thin driver passes it.
What is protocol-first engineering?
Protocol-first engineering asks, for every abstraction layer, whether writing the explicit protocol call makes behavior clearer, not just shorter. Each layer between your code and HTTP, SQL, or the filesystem is a place a failure can hide.
The question that replaces "is this dependency popular?"
The Bare Metal Software fieldbook's Complexity Ledger discipline (Chapter 3) reframes every dependency decision around one question, not "is this popular" or "would this save typing": what obligation does this dependency create, and what complexity does it actually remove? Its own worked example names the layer most teams add without asking: "Hide SQL → Would explicit SQL make behavior clearer?" — an ORM doesn't remove SQL, it adds a translation layer between you and the SQL that's still actually running.
The committed default, stated directly
Chapter 5's Stack Defaults chapter states the default plainly (p.35): "one Rust program, SQLite for the data, DuckDB for reporting, HTML with HTMX or Datastar for the screens, Caddy in front, systemd underneath, and an email provider on the side" — naming, at p.44, the exact libraries: Axum on the Tokio runtime, rusqlite with hand-written SQL, Askama templates ("ordinary HTML files a designer can read"), serde for serialization. Its own conclusion: "There is no ORM, no bundler, and no second language on the server."
A layer audit of this repository's own choices
This isn't a claim in the abstract — it's this system's actual architecture, checkable in the source.
| Capability | Layer-minimized choice (this repo) | What it avoided |
|---|---|---|
| Database access | rusqlite, hand-written SQL | An ORM's query-builder translation layer |
| Web framework | Axum directly on the Tokio runtime | A heavier batteries-included framework |
| Templates | Askama (compile-time, plain HTML) | A client-side templating framework and its build step |
| URL-safe encoding | A hand-written 15-line percent_encode function | A crate dependency for a single, narrow, already-known-alphabet use |
| IP-salt hashing | Direct sha2 call, no wrapper crate | An abstraction layer over a one-line hash call |
None of these are anti-dependency dogma — this codebase does depend on Axum, Tokio, rusqlite, Askama, and several others. The discipline is that each one is there because a direct protocol call would genuinely be worse, not because it's the default choice nobody questioned.
Engineering reference only, synthesized from the Bare Metal Software
fieldbook (Shahid N. Shah, 2026) and this repository's own
docs/decisions/adr-001-core-tech-stack.md, which cites the
fieldbook by chapter and page number.
Provenance & review state
- Last reviewed
- Sources
-
- Bare Metal Software (Shahid N. Shah, 2026), Ch. 3 & Ch. 5 — Netspective Communications LLC
- Ingested from
-