LLMs Are Not the Next Abstraction Layer
Why treating LLMs like compilers is the wrong mental model, and what abstraction actually requires.
People keep saying LLMs are just the next abstraction layer.
Assembly → C → Python → prompts.
I get why this frame is attractive. It is clean. It makes the current chaos feel like normal engineering progress.
But I think it is wrong.
I already wrote about LLMs as Frieren demons →: language-shaped entities that can mimic meaning without carrying the human referent behind the words.
This is the engineering version of the same warning: fluency is not abstraction.
A real abstraction hides complexity behind a contract.
Python hides machine code because the compiler/interpreter has deterministic semantics. Same program, same runtime, same environment: same behavior. Not perfect in every cursed edge case, but stable enough that you can treat the lower layer as infrastructure.
You do not review emitted machine instructions every time you write:
x = users[0].email
You trust the layer because the layer has guarantees.
LLMs do not have that shape.
An LLM is not a compiler for intent. It is closer to a very useful alien autocomplete that learned the shape of code, docs, tests, tickets, and architectural arguments.
Sometimes it gives you correct code.
Sometimes it gives you a security bug with beautiful indentation.
Sometimes it gives you a business rule that sounds reasonable and quietly breaks the product.
That difference matters.
A compiler reduces what you need to inspect. An LLM increases what you need to verify.
That is where the “next abstraction layer” argument breaks for me.
Abstraction lets you forget safely.
LLMs force you to remember more of the system: where state lives, who owns truth, what failure modes exist, what logs prove, what breaks when one piece disappears.
If you skip that, the model still produces code.
It just produces code into a theory vacuum.
Peter Naur had the better frame in 1985: programming is theory building. The code is not the program. The program is the mental model inside the builder’s head: why pieces exist, how they interact, what assumptions keep them alive.
LLMs generate the shadow.
They do not automatically generate the theory.
This is the trap of vibe coding at scale. You can produce 7,000 lines in a day and still have no system.
No ownership boundaries.
No feedback loops.
No blast-radius understanding.
Just syntax arranged into the shape of a product.
And the worst part: it often works.
Until it meets reality.
Then nobody knows where the bug lives because nobody built the map.
So I do not think the shift is “developers move from code to prompts.”
That is too shallow.
The shift is: developers move from typing implementation to governing systems.
Prompting is part of that, sure. But prompting is not the job.
The job is constraints, invariants, feedback, review, architecture, and taste. It is knowing when the model gave you something locally correct but globally stupid.
The Harvard “jagged frontier” frame is useful here: models are sharp in some places and weirdly dull in others, sometimes in the same session.
The new skill is knowing which edge you are standing on.
My operating manual is becoming simple:
- Before prompting, draw the system.
- Before accepting code, ask where state lives.
- Before merging, ask what proves this works.
- Before deleting anything, trace the blast radius.
- Before trusting the model, name the contract it cannot guarantee.
This is not an anti-AI take.
I use these tools constantly. Let them write boilerplate. Let them generate migrations. Let them draft tests, explore alternatives, explain unfamiliar code, and compress the boring parts of the craft.
Just do not confuse output velocity with abstraction.
LLMs are not the layer above Python.
They are something stranger: a collaborator beside you, speaking in code-shaped language, useful when constrained, dangerous when believed too easily.
The future senior engineer is not the person who types fastest.
It is the person who can hold the theory while machines generate the shadows.