Why write 'X' from scratch?
2025-04-30
why write 'x' from scratch?
in a world of pre-built everything, most developers have forgotten how to build anything truly original.
they live inside abstractions, importing libraries without ever questioning what those libraries actually do.
but there's a different path—the builder's path.
real engineers don't just assemble parts—they create systems from first principles.
not because it's always practical, but because it teaches you how computing really works.
you see the bits shift. you understand the architecture, and you stop guessing.
"when you build from scratch, you begin to hear the hum of the machine. that's when you know you've crossed over."
— technical truth #427
example: write your own auth
most developers treat authentication like black magic. but it's not.
if you want to understand the internet, you should know how to build an auth system from scratch.
- cookies aren't just headers—they're byte-level data passed across borders.
- jwts are base64-encoded json + a signature. understand the flow.
- hashing passwords?
bcrypt
is just a slow, salted blowfish variant. - csrf? a side effect of how browsers naively attach cookies.
delegating all of this without ever understanding it?
that's not engineering. that's babysitting someone else's work. (or as some would refer to it, being a "glue engineer")
use raw sockets at least once
you'll never truly understand the web if you haven't opened a socket by hand.
frameworks abstract it all away—but at what cost?
int socket_fd = socket(af_inet, sock_stream, 0);
bind(socket_fd, ...);
listen(socket_fd, 10);
here's what you'll learn:
- tcp isn't a black box. it's just packets, acks, and sequence numbers.
- blocking i/o can strangle your throughput.
- http is just a string-based protocol. you can parse it yourself.
after this, frameworks feel lighter.
you'll see what they're hiding—and when to bypass them.
rebuild the foundations
if you want to go deeper, try recreating the core tools of our field:
- a shell: input parsing + fork() and exec()
- a terminal: ansi codes, buffers, and some trickery
- a memory allocator: malloc() is just a smart pointer manager
- a compiler: recursive descent parsing isn't sorcery—just logic
each of these projects will teach you something fundamental about how computers work.
you'll start seeing patterns everywhere.
the magic fades, replaced by understanding.
the hidden cost of abstraction
every layer of abstraction comes with a price:
- performance: each abstraction adds overhead. sometimes it matters.
- debugging: when things break, you need to understand the layers below.
- innovation: you can't improve what you don't understand.
- security: attackers understand the layers you ignore.
- understanding: the trap with abstraction, is that they deceive into thinking you already understand the concept, thus hindering your natural curiosity.
this post isn't about rejecting abstractions, it's about knowing when to peel them back.
the path forward
building from scratch isn't about being a purist.
it's about developing the ability to see through abstractions when needed.
to debug at the root cause, not the symptom.
to innovate, not just assemble.
and hey, even if you never use it in prod, you will still learn a lot from it.
when you understand the layers below you, you become antifragile.
you don't just memorize solutions—you reason from first principles.
disclaimer
this post isn’t saying “never use frameworks” or “reinvent every wheel.”
use whatever tools make you productive.
but use them after you understand what they’re doing under the hood.
tools should serve you.
not shield you from understanding.
— nathan